home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / texture.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  107.9 KB  |  3,505 lines

  1. /* $Id: texture.c,v 1.19 1997/03/04 19:55:58 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: texture.c,v $
  26.  * Revision 1.19  1997/03/04 19:55:58  brianp
  27.  * small texture sampling optimizations.  better comments.
  28.  *
  29.  * Revision 1.18  1997/03/04 19:19:20  brianp
  30.  * fixed a number of problems with texture borders
  31.  *
  32.  * Revision 1.17  1997/02/27 19:58:08  brianp
  33.  * call gl_problem() instead of gl_warning()
  34.  *
  35.  * Revision 1.16  1997/02/09 19:53:43  brianp
  36.  * now use TEXTURE_xD enable constants
  37.  *
  38.  * Revision 1.15  1997/02/09 18:53:14  brianp
  39.  * added GL_EXT_texture3D support
  40.  *
  41.  * Revision 1.14  1997/01/30 21:06:03  brianp
  42.  * added some missing glGetTexLevelParameter() GLenums
  43.  *
  44.  * Revision 1.13  1997/01/16 03:36:01  brianp
  45.  * added calls to device driver TexParameter() and TexEnv() functions
  46.  *
  47.  * Revision 1.12  1997/01/09 19:48:30  brianp
  48.  * better error checking
  49.  * added gl_texturing_enabled()
  50.  *
  51.  * Revision 1.11  1996/12/20 20:22:30  brianp
  52.  * linear interpolation between mipmap levels was reverse weighted
  53.  * max mipmap level was incorrectly tested for
  54.  *
  55.  * Revision 1.10  1996/12/12 22:33:05  brianp
  56.  * minor changes to gl_texgen()
  57.  *
  58.  * Revision 1.9  1996/12/07 10:35:41  brianp
  59.  * implmented glGetTexGen*() functions
  60.  *
  61.  * Revision 1.8  1996/11/14 01:03:09  brianp
  62.  * removed const's from gl_texgen() function to avoid VMS compiler warning
  63.  *
  64.  * Revision 1.7  1996/11/08 02:19:52  brianp
  65.  * gl_do_texgen() replaced with gl_texgen()
  66.  *
  67.  * Revision 1.6  1996/10/26 17:17:30  brianp
  68.  * glTexGen GL_EYE_PLANE vector now transformed by inverse modelview matrix
  69.  *
  70.  * Revision 1.5  1996/10/11 03:42:38  brianp
  71.  * replaced old _EXT symbols
  72.  *
  73.  * Revision 1.4  1996/09/27 01:30:24  brianp
  74.  * added missing default cases to switches
  75.  *
  76.  * Revision 1.3  1996/09/15 14:18:55  brianp
  77.  * now use GLframebuffer and GLvisual
  78.  *
  79.  * Revision 1.2  1996/09/15 01:48:58  brianp
  80.  * removed #define NULL 0
  81.  *
  82.  * Revision 1.1  1996/09/13 01:38:16  brianp
  83.  * Initial revision
  84.  *
  85.  */
  86.  
  87.  
  88. #include <assert.h>
  89. #include <math.h>
  90. #include <stdio.h>
  91. #include <stdlib.h>
  92. #include <string.h>
  93. #include "context.h"
  94. #include "dlist.h"
  95. #include "macros.h"
  96. #include "matrix.h"
  97. #include "pb.h"
  98. #include "teximage.h"
  99. #include "texture.h"
  100. #include "types.h"
  101. #include "xform.h"
  102.  
  103.  
  104.  
  105.  
  106. /**********************************************************************/
  107. /*                       Texture Environment                          */
  108. /**********************************************************************/
  109.  
  110.  
  111.  
  112. void gl_TexEnvfv( GLcontext *ctx,
  113.                   GLenum target, GLenum pname, const GLfloat *param )
  114. {
  115.    if (INSIDE_BEGIN_END(ctx)) {
  116.       gl_error( ctx, GL_INVALID_OPERATION, "glTexEnv" );
  117.       return;
  118.    }
  119.  
  120.    if (target!=GL_TEXTURE_ENV) {
  121.       gl_error( ctx, GL_INVALID_ENUM, "glTexEnv(target)" );
  122.       return;
  123.    }
  124.  
  125.    if (pname==GL_TEXTURE_ENV_MODE) {
  126.       GLenum mode = (GLenum) (GLint) *param;
  127.       switch (mode) {
  128.      case GL_MODULATE:
  129.      case GL_BLEND:
  130.      case GL_DECAL:
  131.      case GL_REPLACE:
  132.         ctx->Texture.EnvMode = mode;
  133.         break;
  134.      default:
  135.         gl_error( ctx, GL_INVALID_ENUM, "glTexEnv(param)" );
  136.         return;
  137.       }
  138.    }
  139.    else if (pname==GL_TEXTURE_ENV_COLOR) {
  140.       ctx->Texture.EnvColor[0] = CLAMP( param[0], 0.0, 1.0 );
  141.       ctx->Texture.EnvColor[1] = CLAMP( param[1], 0.0, 1.0 );
  142.       ctx->Texture.EnvColor[2] = CLAMP( param[2], 0.0, 1.0 );
  143.       ctx->Texture.EnvColor[3] = CLAMP( param[3], 0.0, 1.0 );
  144.    }
  145.    else {
  146.       gl_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
  147.       return;
  148.    }
  149.  
  150.    /* Tell device driver about the new texture environment */
  151.    if (ctx->Driver.TexEnv) {
  152.       (*ctx->Driver.TexEnv)( ctx, pname, param );
  153.    }
  154. }
  155.  
  156.  
  157.  
  158.  
  159.  
  160. void gl_GetTexEnvfv( GLcontext *ctx,
  161.                      GLenum target, GLenum pname, GLfloat *params )
  162. {
  163.    if (target!=GL_TEXTURE_ENV) {
  164.       gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  165.       return;
  166.    }
  167.    switch (pname) {
  168.       case GL_TEXTURE_ENV_MODE:
  169.          *params = (GLfloat) ctx->Texture.EnvMode;
  170.      break;
  171.       case GL_TEXTURE_ENV_COLOR:
  172.      COPY_4V( params, ctx->Texture.EnvColor );
  173.      break;
  174.       default:
  175.          gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  176.    }
  177. }
  178.  
  179.  
  180. void gl_GetTexEnviv( GLcontext *ctx,
  181.                      GLenum target, GLenum pname, GLint *params )
  182. {
  183.    if (target!=GL_TEXTURE_ENV) {
  184.       gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  185.       return;
  186.    }
  187.    switch (pname) {
  188.       case GL_TEXTURE_ENV_MODE:
  189.          *params = (GLint) ctx->Texture.EnvMode;
  190.      break;
  191.       case GL_TEXTURE_ENV_COLOR:
  192.      params[0] = FLOAT_TO_INT( ctx->Texture.EnvColor[0] );
  193.      params[1] = FLOAT_TO_INT( ctx->Texture.EnvColor[1] );
  194.      params[2] = FLOAT_TO_INT( ctx->Texture.EnvColor[2] );
  195.      params[3] = FLOAT_TO_INT( ctx->Texture.EnvColor[3] );
  196.      break;
  197.       default:
  198.          gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  199.    }
  200. }
  201.  
  202.  
  203.  
  204.  
  205. /**********************************************************************/
  206. /*                       Texture Parameters                           */
  207. /**********************************************************************/
  208.  
  209.  
  210. void gl_TexParameterfv( GLcontext *ctx,
  211.                         GLenum target, GLenum pname, const GLfloat *params )
  212. {
  213.    GLenum eparam = (GLenum) (GLint) params[0];
  214.    GLuint ddTexObject;
  215.  
  216.    if (target==GL_TEXTURE_1D) {
  217.       switch (pname) {
  218.      case GL_TEXTURE_MIN_FILTER:
  219.         if (eparam==GL_NEAREST || eparam==GL_LINEAR
  220.         || eparam==GL_NEAREST_MIPMAP_NEAREST
  221.         || eparam==GL_LINEAR_MIPMAP_NEAREST
  222.         || eparam==GL_NEAREST_MIPMAP_LINEAR
  223.         || eparam==GL_LINEAR_MIPMAP_LINEAR) {
  224.            ctx->Texture.Current1D->MinFilter = eparam;
  225.                ctx->NewState |= NEW_TEXTURING;
  226.         }
  227.         else {
  228.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  229.                return;
  230.         }
  231.         break;
  232.      case GL_TEXTURE_MAG_FILTER:
  233.         if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
  234.            ctx->Texture.Current1D->MagFilter = eparam;
  235.                ctx->NewState |= NEW_TEXTURING;
  236.         }
  237.         else {
  238.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  239.                return;
  240.         }
  241.         break;
  242.      case GL_TEXTURE_WRAP_S:
  243.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  244.            ctx->Texture.Current1D->WrapS = eparam;
  245.         }
  246.         else {
  247.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  248.                return;
  249.         }
  250.         break;
  251.      case GL_TEXTURE_WRAP_T:
  252.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  253.            ctx->Texture.Current1D->WrapT = eparam;
  254.         }
  255.         else {
  256.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  257.                return;
  258.         }
  259.         break;
  260.          case GL_TEXTURE_BORDER_COLOR:
  261.             {
  262.                GLint *bc = ctx->Texture.Current1D->BorderColor;
  263.                bc[0] = CLAMP((GLint)(params[0]*255.0), 0, 255);
  264.                bc[1] = CLAMP((GLint)(params[1]*255.0), 0, 255);
  265.                bc[2] = CLAMP((GLint)(params[2]*255.0), 0, 255);
  266.                bc[3] = CLAMP((GLint)(params[3]*255.0), 0, 255);
  267.             }
  268.             break;
  269.      default:
  270.         gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(pname)" );
  271.             return;
  272.       }
  273.       ddTexObject = ctx->Texture.Current1D->Name;
  274.    }
  275.    else if (target==GL_TEXTURE_2D) {
  276.       switch (pname) {
  277.      case GL_TEXTURE_MIN_FILTER:
  278.         if (eparam==GL_NEAREST || eparam==GL_LINEAR
  279.         || eparam==GL_NEAREST_MIPMAP_NEAREST
  280.         || eparam==GL_LINEAR_MIPMAP_NEAREST
  281.         || eparam==GL_NEAREST_MIPMAP_LINEAR
  282.         || eparam==GL_LINEAR_MIPMAP_LINEAR) {
  283.            ctx->Texture.Current2D->MinFilter = eparam;
  284.                ctx->NewState |= NEW_TEXTURING;
  285.         }
  286.         else {
  287.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  288.                return;
  289.         }
  290.         break;
  291.      case GL_TEXTURE_MAG_FILTER:
  292.         if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
  293.            ctx->Texture.Current2D->MagFilter = eparam;
  294.                ctx->NewState |= NEW_TEXTURING;
  295.         }
  296.         else {
  297.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  298.                return;
  299.         }
  300.         break;
  301.      case GL_TEXTURE_WRAP_S:
  302.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  303.            ctx->Texture.Current2D->WrapS = eparam;
  304.         }
  305.         else {
  306.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  307.                return;
  308.         }
  309.         break;
  310.      case GL_TEXTURE_WRAP_T:
  311.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  312.            ctx->Texture.Current2D->WrapT = eparam;
  313.         }
  314.         else {
  315.            gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  316.                return;
  317.         }
  318.         break;
  319.          case GL_TEXTURE_BORDER_COLOR:
  320.             {
  321.                GLint *bc = ctx->Texture.Current2D->BorderColor;
  322.                bc[0] = CLAMP((GLint)(params[0]*255.0), 0, 255);
  323.                bc[1] = CLAMP((GLint)(params[1]*255.0), 0, 255);
  324.                bc[2] = CLAMP((GLint)(params[2]*255.0), 0, 255);
  325.                bc[3] = CLAMP((GLint)(params[3]*255.0), 0, 255);
  326.             }
  327.             break;
  328.      default:
  329.         gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(pname)" );
  330.             return;
  331.       }
  332.       ddTexObject = ctx->Texture.Current1D->Name;
  333.    }
  334.    else if (target==GL_TEXTURE_3D_EXT) {
  335.       switch (pname) {
  336.          case GL_TEXTURE_MIN_FILTER:
  337.             if (eparam==GL_NEAREST || eparam==GL_LINEAR
  338.                 || eparam==GL_NEAREST_MIPMAP_NEAREST
  339.                 || eparam==GL_LINEAR_MIPMAP_NEAREST
  340.                 || eparam==GL_NEAREST_MIPMAP_LINEAR
  341.                 || eparam==GL_LINEAR_MIPMAP_LINEAR) {
  342.                ctx->Texture.Current3D->MinFilter = eparam;
  343.                ctx->NewState |= NEW_TEXTURING;
  344.             }
  345.             else {
  346.                gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  347.             }
  348.             break;
  349.          case GL_TEXTURE_MAG_FILTER:
  350.             if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
  351.                ctx->Texture.Current3D->MagFilter = eparam;
  352.                ctx->NewState |= NEW_TEXTURING;
  353.             }
  354.             else {
  355.                gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  356.             }
  357.             break;
  358.          case GL_TEXTURE_WRAP_S:
  359.             if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  360.                ctx->Texture.Current3D->WrapS = eparam;
  361.             }
  362.             else {
  363.                gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  364.             }
  365.            break;
  366.          case GL_TEXTURE_WRAP_T:
  367.             if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  368.                ctx->Texture.Current3D->WrapT = eparam;
  369.             }
  370.             else {
  371.                gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  372.             }
  373.             break;
  374.          case GL_TEXTURE_WRAP_R_EXT:
  375.             if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  376.                ctx->Texture.Current3D->WrapR = eparam;
  377.             }
  378.             else {
  379.                gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
  380.             }
  381.             break;
  382.          case GL_TEXTURE_BORDER_COLOR:
  383.             {
  384.                GLint *bc = ctx->Texture.Current3D->BorderColor;
  385.                bc[0] = CLAMP((GLint)(params[0]*255.0), 0, 255);
  386.                bc[1] = CLAMP((GLint)(params[1]*255.0), 0, 255);
  387.                bc[2] = CLAMP((GLint)(params[2]*255.0), 0, 255);
  388.                bc[3] = CLAMP((GLint)(params[3]*255.0), 0, 255);
  389.             }
  390.             break;
  391.          default:
  392.             gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(pname)" );
  393.       }
  394.    }
  395.    else {
  396.       gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
  397.       return;
  398.    }
  399.  
  400.    /* Pass this glTexParameter*() call to the device driver. */
  401.    if (ctx->Driver.TexParameter) {
  402.       (*ctx->Driver.TexParameter)( ctx, target, ddTexObject, pname, params );
  403.    }
  404. }
  405.  
  406.  
  407.  
  408. void gl_GetTexLevelParameterfv( GLcontext *ctx, GLenum target, GLint level,
  409.                                 GLenum pname, GLfloat *params )
  410. {
  411.    struct gl_texture_image *tex;
  412.  
  413.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  414.       gl_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameterfv" );
  415.       return;
  416.    }
  417.  
  418.    switch (target) {
  419.       case GL_TEXTURE_1D:
  420.          tex = ctx->Texture.Current1D->Image[level];
  421.          switch (pname) {
  422.         case GL_TEXTURE_WIDTH:
  423.            *params = (GLfloat) tex->Width;
  424.            break;
  425.         case GL_TEXTURE_COMPONENTS:
  426.            *params = (GLfloat) tex->Format;
  427.            break;
  428.         case GL_TEXTURE_BORDER:
  429.            *params = (GLfloat) tex->Border;
  430.            break;
  431.             case GL_TEXTURE_RED_SIZE:
  432.             case GL_TEXTURE_GREEN_SIZE:
  433.             case GL_TEXTURE_BLUE_SIZE:
  434.             case GL_TEXTURE_ALPHA_SIZE:
  435.             case GL_TEXTURE_INTENSITY_SIZE:
  436.             case GL_TEXTURE_LUMINANCE_SIZE:
  437.                *params = 8.0;  /* 8-bits */
  438.                break;
  439.         default:
  440.            gl_error( ctx, GL_INVALID_ENUM,
  441.                          "glGetTexLevelParameterfv(pname)" );
  442.      }
  443.      break;
  444.       case GL_TEXTURE_2D:
  445.          tex = ctx->Texture.Current2D->Image[level];
  446.      switch (pname) {
  447.         case GL_TEXTURE_WIDTH:
  448.            *params = (GLfloat) tex->Width;
  449.            break;
  450.         case GL_TEXTURE_HEIGHT:
  451.            *params = (GLfloat) tex->Height;
  452.            break;
  453.         case GL_TEXTURE_COMPONENTS:
  454.            *params = (GLfloat) tex->Format;
  455.            break;
  456.         case GL_TEXTURE_BORDER:
  457.            *params = (GLfloat) tex->Border;
  458.            break;
  459.             case GL_TEXTURE_RED_SIZE:
  460.             case GL_TEXTURE_GREEN_SIZE:
  461.             case GL_TEXTURE_BLUE_SIZE:
  462.             case GL_TEXTURE_ALPHA_SIZE:
  463.             case GL_TEXTURE_INTENSITY_SIZE:
  464.             case GL_TEXTURE_LUMINANCE_SIZE:
  465.                *params = 8.0;  /* 8-bits */
  466.                break;
  467.         default:
  468.            gl_error( ctx, GL_INVALID_ENUM,
  469.                          "glGetTexLevelParameterfv(pname)" );
  470.      }
  471.      break;
  472.       case GL_TEXTURE_3D_EXT:
  473.          tex = ctx->Texture.Current3D->Image[level];
  474.          switch (pname) {
  475.             case GL_TEXTURE_WIDTH:
  476.                *params = (GLfloat) tex->Width;
  477.                break;
  478.             case GL_TEXTURE_HEIGHT:
  479.                *params = (GLfloat) tex->Height;
  480.                break;
  481.             case GL_TEXTURE_DEPTH_EXT:
  482.                *params = (GLfloat) tex->Depth;
  483.                break;
  484.             case GL_TEXTURE_COMPONENTS:
  485.                *params = (GLfloat) tex->Format;
  486.                break;
  487.             case GL_TEXTURE_BORDER:
  488.                *params = (GLfloat) tex->Border;
  489.                break;
  490.             default:
  491.                gl_error( ctx, GL_INVALID_ENUM,
  492.                          "glGetTexLevelParameterfv(pname)" );
  493.          }
  494.          break;
  495.       case GL_PROXY_TEXTURE_1D:
  496.          tex = ctx->Texture.Proxy1D->Image[level];
  497.          switch (pname) {
  498.         case GL_TEXTURE_WIDTH:
  499.            *params = (GLfloat) tex->Width;
  500.            break;
  501.         case GL_TEXTURE_COMPONENTS:
  502.            *params = (GLfloat) tex->Format;
  503.            break;
  504.         case GL_TEXTURE_BORDER:
  505.            *params = (GLfloat) tex->Border;
  506.            break;
  507.             case GL_TEXTURE_RED_SIZE:
  508.             case GL_TEXTURE_GREEN_SIZE:
  509.             case GL_TEXTURE_BLUE_SIZE:
  510.             case GL_TEXTURE_ALPHA_SIZE:
  511.             case GL_TEXTURE_INTENSITY_SIZE:
  512.             case GL_TEXTURE_LUMINANCE_SIZE:
  513.                *params = 8.0;  /* 8-bits */
  514.                break;
  515.         default:
  516.            gl_error( ctx, GL_INVALID_ENUM,
  517.                          "glGetTexLevelParameterfv(pname)" );
  518.      }
  519.      break;
  520.       case GL_PROXY_TEXTURE_2D:
  521.          tex = ctx->Texture.Proxy2D->Image[level];
  522.      switch (pname) {
  523.         case GL_TEXTURE_WIDTH:
  524.            *params = (GLfloat) tex->Width;
  525.            break;
  526.         case GL_TEXTURE_HEIGHT:
  527.            *params = (GLfloat) tex->Height;
  528.            break;
  529.         case GL_TEXTURE_COMPONENTS:
  530.            *params = (GLfloat) tex->Format;
  531.            break;
  532.         case GL_TEXTURE_BORDER:
  533.            *params = (GLfloat) tex->Border;
  534.            break;
  535.             case GL_TEXTURE_RED_SIZE:
  536.             case GL_TEXTURE_GREEN_SIZE:
  537.             case GL_TEXTURE_BLUE_SIZE:
  538.             case GL_TEXTURE_ALPHA_SIZE:
  539.             case GL_TEXTURE_INTENSITY_SIZE:
  540.             case GL_TEXTURE_LUMINANCE_SIZE:
  541.                *params = 8.0;  /* 8-bits */
  542.                break;
  543.         default:
  544.            gl_error( ctx, GL_INVALID_ENUM,
  545.                          "glGetTexLevelParameterfv(pname)" );
  546.      }
  547.      break;
  548.       case GL_PROXY_TEXTURE_3D_EXT:
  549.          tex = ctx->Texture.Proxy3D->Image[level];
  550.      switch (pname) {
  551.         case GL_TEXTURE_WIDTH:
  552.            *params = (GLfloat) tex->Width;
  553.            break;
  554.         case GL_TEXTURE_HEIGHT:
  555.            *params = (GLfloat) tex->Height;
  556.            break;
  557.         case GL_TEXTURE_DEPTH_EXT:
  558.            *params = (GLfloat) tex->Depth;
  559.            break;
  560.         case GL_TEXTURE_COMPONENTS:
  561.            *params = (GLfloat) tex->Format;
  562.            break;
  563.         case GL_TEXTURE_BORDER:
  564.            *params = (GLfloat) tex->Border;
  565.            break;
  566.             case GL_TEXTURE_RED_SIZE:
  567.             case GL_TEXTURE_GREEN_SIZE:
  568.             case GL_TEXTURE_BLUE_SIZE:
  569.             case GL_TEXTURE_ALPHA_SIZE:
  570.             case GL_TEXTURE_INTENSITY_SIZE:
  571.             case GL_TEXTURE_LUMINANCE_SIZE:
  572.                *params = 8.0;  /* 8-bits */
  573.                break;
  574.         default:
  575.            gl_error( ctx, GL_INVALID_ENUM,
  576.                          "glGetTexLevelParameterfv(pname)" );
  577.      }
  578.      break;
  579.      default:
  580.      gl_error( ctx, GL_INVALID_ENUM, "glGetTexLevelParameterfv(target)" );
  581.    }     
  582. }
  583.  
  584.  
  585.  
  586. void gl_GetTexLevelParameteriv( GLcontext *ctx, GLenum target, GLint level,
  587.                                 GLenum pname, GLint *params )
  588. {
  589.    struct gl_texture_image *tex;
  590.  
  591.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  592.       gl_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameteriv" );
  593.       return;
  594.    }
  595.  
  596.    switch (target) {
  597.       case GL_TEXTURE_1D:
  598.          tex = ctx->Texture.Current1D->Image[level];
  599.          switch (pname) {
  600.         case GL_TEXTURE_WIDTH:
  601.            *params = tex->Width;
  602.            break;
  603.         case GL_TEXTURE_COMPONENTS:
  604.            *params = tex->Format;
  605.            break;
  606.         case GL_TEXTURE_BORDER:
  607.            *params = tex->Border;
  608.            break;
  609.             case GL_TEXTURE_RED_SIZE:
  610.             case GL_TEXTURE_GREEN_SIZE:
  611.             case GL_TEXTURE_BLUE_SIZE:
  612.             case GL_TEXTURE_ALPHA_SIZE:
  613.             case GL_TEXTURE_INTENSITY_SIZE:
  614.             case GL_TEXTURE_LUMINANCE_SIZE:
  615.                *params = 8;  /* 8-bits */
  616.                break;
  617.         default:
  618.            gl_error( ctx, GL_INVALID_ENUM,
  619.                          "glGetTexLevelParameteriv(pname)" );
  620.      }
  621.      break;
  622.       case GL_TEXTURE_2D:
  623.          tex = ctx->Texture.Current2D->Image[level];
  624.      switch (pname) {
  625.         case GL_TEXTURE_WIDTH:
  626.            *params = tex->Width;
  627.            break;
  628.         case GL_TEXTURE_HEIGHT:
  629.            *params = tex->Height;
  630.            break;
  631.         case GL_TEXTURE_COMPONENTS:
  632.            *params = tex->Format;
  633.            break;
  634.         case GL_TEXTURE_BORDER:
  635.            *params = tex->Border;
  636.            break;
  637.             case GL_TEXTURE_RED_SIZE:
  638.             case GL_TEXTURE_GREEN_SIZE:
  639.             case GL_TEXTURE_BLUE_SIZE:
  640.             case GL_TEXTURE_ALPHA_SIZE:
  641.             case GL_TEXTURE_INTENSITY_SIZE:
  642.             case GL_TEXTURE_LUMINANCE_SIZE:
  643.                *params = 8;  /* 8-bits */
  644.                break;
  645.         default:
  646.            gl_error( ctx, GL_INVALID_ENUM,
  647.                          "glGetTexLevelParameteriv(pname)" );
  648.      }
  649.      break;
  650.       case GL_TEXTURE_3D_EXT:
  651.          tex = ctx->Texture.Current3D->Image[level];
  652.          switch (pname) {
  653.             case GL_TEXTURE_WIDTH:
  654.                *params = tex->Width;
  655.                break;
  656.             case GL_TEXTURE_HEIGHT:
  657.                *params = tex->Height;
  658.                break;
  659.             case GL_TEXTURE_DEPTH_EXT:
  660.                *params = tex->Depth;
  661.                break;
  662.             case GL_TEXTURE_COMPONENTS:
  663.                *params = tex->Format;
  664.                break;
  665.             case GL_TEXTURE_BORDER:
  666.                *params = tex->Border;
  667.                break;
  668.             default:
  669.                gl_error( ctx, GL_INVALID_ENUM,
  670.                          "glGetTexLevelParameteriv(pname)" );
  671.          }
  672.          break;
  673.       case GL_PROXY_TEXTURE_1D:
  674.          tex = ctx->Texture.Proxy1D->Image[level];
  675.          switch (pname) {
  676.         case GL_TEXTURE_WIDTH:
  677.            *params = tex->Width;
  678.            break;
  679.         case GL_TEXTURE_COMPONENTS:
  680.            *params = tex->Format;
  681.            break;
  682.         case GL_TEXTURE_BORDER:
  683.            *params = tex->Border;
  684.            break;
  685.             case GL_TEXTURE_RED_SIZE:
  686.             case GL_TEXTURE_GREEN_SIZE:
  687.             case GL_TEXTURE_BLUE_SIZE:
  688.             case GL_TEXTURE_ALPHA_SIZE:
  689.             case GL_TEXTURE_INTENSITY_SIZE:
  690.             case GL_TEXTURE_LUMINANCE_SIZE:
  691.                *params = 8;  /* 8-bits */
  692.                break;
  693.         default:
  694.            gl_error( ctx, GL_INVALID_ENUM,
  695.                          "glGetTexLevelParameteriv(pname)" );
  696.      }
  697.      break;
  698.       case GL_PROXY_TEXTURE_2D:
  699.          tex = ctx->Texture.Proxy2D->Image[level];
  700.      switch (pname) {
  701.         case GL_TEXTURE_WIDTH:
  702.            *params = tex->Width;
  703.            break;
  704.         case GL_TEXTURE_HEIGHT:
  705.            *params = tex->Height;
  706.            break;
  707.         case GL_TEXTURE_COMPONENTS:
  708.            *params = tex->Format;
  709.            break;
  710.         case GL_TEXTURE_BORDER:
  711.            *params = tex->Border;
  712.            break;
  713.             case GL_TEXTURE_RED_SIZE:
  714.             case GL_TEXTURE_GREEN_SIZE:
  715.             case GL_TEXTURE_BLUE_SIZE:
  716.             case GL_TEXTURE_ALPHA_SIZE:
  717.             case GL_TEXTURE_INTENSITY_SIZE:
  718.             case GL_TEXTURE_LUMINANCE_SIZE:
  719.                *params = 8;  /* 8-bits */
  720.                break;
  721.         default:
  722.            gl_error( ctx, GL_INVALID_ENUM,
  723.                          "glGetTexLevelParameteriv(pname)" );
  724.      }
  725.      break;
  726.       case GL_PROXY_TEXTURE_3D_EXT:
  727.          tex = ctx->Texture.Proxy3D->Image[level];
  728.      switch (pname) {
  729.         case GL_TEXTURE_WIDTH:
  730.            *params = tex->Width;
  731.            break;
  732.         case GL_TEXTURE_HEIGHT:
  733.            *params = tex->Height;
  734.            break;
  735.         case GL_TEXTURE_DEPTH_EXT:
  736.            *params = tex->Depth;
  737.            break;
  738.         case GL_TEXTURE_COMPONENTS:
  739.            *params = tex->Format;
  740.            break;
  741.         case GL_TEXTURE_BORDER:
  742.            *params = tex->Border;
  743.            break;
  744.             case GL_TEXTURE_RED_SIZE:
  745.             case GL_TEXTURE_GREEN_SIZE:
  746.             case GL_TEXTURE_BLUE_SIZE:
  747.             case GL_TEXTURE_ALPHA_SIZE:
  748.             case GL_TEXTURE_INTENSITY_SIZE:
  749.             case GL_TEXTURE_LUMINANCE_SIZE:
  750.                *params = 8;  /* 8-bits */
  751.                break;
  752.         default:
  753.            gl_error( ctx, GL_INVALID_ENUM,
  754.                          "glGetTexLevelParameteriv(pname)" );
  755.      }
  756.      break;
  757.      default:
  758.      gl_error( ctx, GL_INVALID_ENUM, "glGetTexLevelParameteriv(target)" );
  759.    }     
  760. }
  761.  
  762.  
  763.  
  764.  
  765. void gl_GetTexParameterfv( GLcontext *ctx,
  766.                            GLenum target, GLenum pname, GLfloat *params )
  767. {
  768.    switch (target) {
  769.       case GL_TEXTURE_1D:
  770.          switch (pname) {
  771.         case GL_TEXTURE_MAG_FILTER:
  772.            *params = (GLfloat) ctx->Texture.Current1D->MagFilter;
  773.            break;
  774.         case GL_TEXTURE_MIN_FILTER:
  775.            *params = (GLfloat) ctx->Texture.Current1D->MinFilter;
  776.            break;
  777.         case GL_TEXTURE_WRAP_S:
  778.            *params = (GLfloat) ctx->Texture.Current1D->WrapS;
  779.            break;
  780.         case GL_TEXTURE_WRAP_T:
  781.            *params = (GLfloat) ctx->Texture.Current1D->WrapT;
  782.            break;
  783.         case GL_TEXTURE_BORDER_COLOR:
  784.                params[0] = ctx->Texture.Current1D->BorderColor[0] / 255.0f;
  785.                params[1] = ctx->Texture.Current1D->BorderColor[1] / 255.0f;
  786.                params[2] = ctx->Texture.Current1D->BorderColor[2] / 255.0f;
  787.                params[3] = ctx->Texture.Current1D->BorderColor[3] / 255.0f;
  788.            break;
  789.         case GL_TEXTURE_RESIDENT:
  790.                *params = (GLfloat) GL_TRUE;
  791.            break;
  792.             case GL_TEXTURE_PRIORITY:
  793.                *params = ctx->Texture.Current1D->Priority;
  794.            break;
  795.         default:
  796.            gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
  797.      }
  798.          break;
  799.       case GL_TEXTURE_2D:
  800.          switch (pname) {
  801.         case GL_TEXTURE_MAG_FILTER:
  802.            *params = (GLfloat) ctx->Texture.Current2D->MagFilter;
  803.            break;
  804.         case GL_TEXTURE_MIN_FILTER:
  805.            *params = (GLfloat) ctx->Texture.Current2D->MinFilter;
  806.            break;
  807.         case GL_TEXTURE_WRAP_S:
  808.            *params = (GLfloat) ctx->Texture.Current2D->WrapS;
  809.            break;
  810.         case GL_TEXTURE_WRAP_T:
  811.            *params = (GLfloat) ctx->Texture.Current2D->WrapT;
  812.            break;
  813.         case GL_TEXTURE_BORDER_COLOR:
  814.                params[0] = ctx->Texture.Current2D->BorderColor[0] / 255.0f;
  815.                params[1] = ctx->Texture.Current2D->BorderColor[1] / 255.0f;
  816.                params[2] = ctx->Texture.Current2D->BorderColor[2] / 255.0f;
  817.                params[3] = ctx->Texture.Current2D->BorderColor[3] / 255.0f;
  818.                break;
  819.         case GL_TEXTURE_RESIDENT:
  820.                *params = (GLfloat) GL_TRUE;
  821.            break;
  822.         case GL_TEXTURE_PRIORITY:
  823.                *params = ctx->Texture.Current2D->Priority;
  824.            break;
  825.         default:
  826.            gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
  827.      }
  828.      break;
  829.       case GL_TEXTURE_3D_EXT:
  830.          switch (pname) {
  831.             case GL_TEXTURE_MAG_FILTER:
  832.                *params = (GLfloat) ctx->Texture.Current3D->MagFilter;
  833.                break;
  834.             case GL_TEXTURE_MIN_FILTER:
  835.                *params = (GLfloat) ctx->Texture.Current3D->MinFilter;
  836.                break;
  837.             case GL_TEXTURE_WRAP_S:
  838.                *params = (GLfloat) ctx->Texture.Current3D->WrapS;
  839.                break;
  840.             case GL_TEXTURE_WRAP_T:
  841.                *params = (GLfloat) ctx->Texture.Current3D->WrapT;
  842.                break;
  843.             case GL_TEXTURE_WRAP_R_EXT:
  844.                *params = (GLfloat) ctx->Texture.Current3D->WrapR;
  845.                break;
  846.             case GL_TEXTURE_BORDER_COLOR:
  847.                params[0] = ctx->Texture.Current3D->BorderColor[0] / 255.0f;
  848.                params[1] = ctx->Texture.Current3D->BorderColor[1] / 255.0f;
  849.                params[2] = ctx->Texture.Current3D->BorderColor[2] / 255.0f;
  850.                params[3] = ctx->Texture.Current3D->BorderColor[3] / 255.0f;
  851.                break;
  852.             case GL_TEXTURE_RESIDENT:
  853.                *params = (GLfloat) GL_TRUE;
  854.                break;
  855.             case GL_TEXTURE_PRIORITY:
  856.                *params = ctx->Texture.Current3D->Priority;
  857.                break;
  858.             default:
  859.                gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
  860.          }
  861.          break;
  862.       default:
  863.          gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)" );
  864.    }
  865. }
  866.  
  867.  
  868. void gl_GetTexParameteriv( GLcontext *ctx,
  869.                            GLenum target, GLenum pname, GLint *params )
  870. {
  871.    switch (target) {
  872.       case GL_TEXTURE_1D:
  873.          switch (pname) {
  874.         case GL_TEXTURE_MAG_FILTER:
  875.            *params = (GLint) ctx->Texture.Current1D->MagFilter;
  876.            break;
  877.         case GL_TEXTURE_MIN_FILTER:
  878.            *params = (GLint) ctx->Texture.Current1D->MinFilter;
  879.            break;
  880.         case GL_TEXTURE_WRAP_S:
  881.            *params = (GLint) ctx->Texture.Current1D->WrapS;
  882.            break;
  883.         case GL_TEXTURE_WRAP_T:
  884.            *params = (GLint) ctx->Texture.Current1D->WrapT;
  885.            break;
  886.         case GL_TEXTURE_BORDER_COLOR:
  887.                {
  888.                   GLfloat color[4];
  889.                   color[0] = ctx->Texture.Current1D->BorderColor[0]/255.0;
  890.                   color[1] = ctx->Texture.Current1D->BorderColor[1]/255.0;
  891.                   color[2] = ctx->Texture.Current1D->BorderColor[2]/255.0;
  892.                   color[3] = ctx->Texture.Current1D->BorderColor[3]/255.0;
  893.                   params[0] = FLOAT_TO_INT( color[0] );
  894.                   params[1] = FLOAT_TO_INT( color[1] );
  895.                   params[2] = FLOAT_TO_INT( color[2] );
  896.                   params[3] = FLOAT_TO_INT( color[3] );
  897.                }
  898.            break;
  899.         case GL_TEXTURE_RESIDENT:
  900.                *params = (GLint) GL_TRUE;
  901.            break;
  902.         case GL_TEXTURE_PRIORITY:
  903.                *params = (GLint) ctx->Texture.Current1D->Priority;
  904.            break;
  905.         default:
  906.            gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
  907.      }
  908.          break;
  909.       case GL_TEXTURE_2D:
  910.          switch (pname) {
  911.         case GL_TEXTURE_MAG_FILTER:
  912.            *params = (GLint) ctx->Texture.Current2D->MagFilter;
  913.            break;
  914.         case GL_TEXTURE_MIN_FILTER:
  915.            *params = (GLint) ctx->Texture.Current2D->MinFilter;
  916.            break;
  917.         case GL_TEXTURE_WRAP_S:
  918.            *params = (GLint) ctx->Texture.Current2D->WrapS;
  919.            break;
  920.         case GL_TEXTURE_WRAP_T:
  921.            *params = (GLint) ctx->Texture.Current2D->WrapT;
  922.            break;
  923.         case GL_TEXTURE_BORDER_COLOR:
  924.                {
  925.                   GLfloat color[4];
  926.                   color[0] = ctx->Texture.Current2D->BorderColor[0]/255.0;
  927.                   color[1] = ctx->Texture.Current2D->BorderColor[1]/255.0;
  928.                   color[2] = ctx->Texture.Current2D->BorderColor[2]/255.0;
  929.                   color[3] = ctx->Texture.Current2D->BorderColor[3]/255.0;
  930.                   params[0] = FLOAT_TO_INT( color[0] );
  931.                   params[1] = FLOAT_TO_INT( color[1] );
  932.                   params[2] = FLOAT_TO_INT( color[2] );
  933.                   params[3] = FLOAT_TO_INT( color[3] );
  934.                }
  935.            break;
  936.         case GL_TEXTURE_RESIDENT:
  937.                *params = (GLint) GL_TRUE;
  938.            break;
  939.         case GL_TEXTURE_PRIORITY:
  940.                *params = (GLint) ctx->Texture.Current2D->Priority;
  941.            break;
  942.         default:
  943.            gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
  944.      }
  945.      break;
  946.       case GL_TEXTURE_3D_EXT:
  947.          switch (pname) {
  948.             case GL_TEXTURE_MAG_FILTER:
  949.                *params = (GLint) ctx->Texture.Current3D->MagFilter;
  950.                break;
  951.             case GL_TEXTURE_MIN_FILTER:
  952.                *params = (GLint) ctx->Texture.Current3D->MinFilter;
  953.                break;
  954.             case GL_TEXTURE_WRAP_S:
  955.                *params = (GLint) ctx->Texture.Current3D->WrapS;
  956.                break;
  957.             case GL_TEXTURE_WRAP_T:
  958.                *params = (GLint) ctx->Texture.Current3D->WrapT;
  959.                break;
  960.             case GL_TEXTURE_WRAP_R_EXT:
  961.                *params = (GLint) ctx->Texture.Current3D->WrapR;
  962.                break;
  963.             case GL_TEXTURE_BORDER_COLOR:
  964.                {
  965.                   GLfloat color[4];
  966.                   color[0] = ctx->Texture.Current3D->BorderColor[0]/255.0;
  967.                   color[1] = ctx->Texture.Current3D->BorderColor[1]/255.0;
  968.                   color[2] = ctx->Texture.Current3D->BorderColor[2]/255.0;
  969.                   color[3] = ctx->Texture.Current3D->BorderColor[3]/255.0;
  970.                   params[0] = FLOAT_TO_INT( color[0] );
  971.                   params[1] = FLOAT_TO_INT( color[1] );
  972.                   params[2] = FLOAT_TO_INT( color[2] );
  973.                   params[3] = FLOAT_TO_INT( color[3] );
  974.                }
  975.                break;
  976.             case GL_TEXTURE_RESIDENT:
  977.                *params = (GLint) GL_TRUE;
  978.                break;
  979.             case GL_TEXTURE_PRIORITY:
  980.                *params = (GLint) ctx->Texture.Current3D->Priority;
  981.                break;
  982.             default:
  983.                gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
  984.          }
  985.          break;
  986.       default:
  987.          gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameteriv(target)" );
  988.    }
  989. }
  990.  
  991.  
  992.  
  993.  
  994. /**********************************************************************/
  995. /*                    Texture Coord Generation                        */
  996. /**********************************************************************/
  997.  
  998.  
  999. void gl_TexGenfv( GLcontext *ctx,
  1000.                   GLenum coord, GLenum pname, const GLfloat *params )
  1001. {
  1002.    if (INSIDE_BEGIN_END(ctx)) {
  1003.       gl_error( ctx, GL_INVALID_OPERATION, "glTexGenfv" );
  1004.       return;
  1005.    }
  1006.  
  1007.    switch( coord ) {
  1008.       case GL_S:
  1009.          if (pname==GL_TEXTURE_GEN_MODE) {
  1010.         GLenum mode = (GLenum) (GLint) *params;
  1011.         if (mode==GL_OBJECT_LINEAR ||
  1012.         mode==GL_EYE_LINEAR ||
  1013.         mode==GL_SPHERE_MAP) {
  1014.            ctx->Texture.GenModeS = mode;
  1015.         }
  1016.         else {
  1017.            gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
  1018.            return;
  1019.         }
  1020.      }
  1021.      else if (pname==GL_OBJECT_PLANE) {
  1022.         ctx->Texture.ObjectPlaneS[0] = params[0];
  1023.         ctx->Texture.ObjectPlaneS[1] = params[1];
  1024.         ctx->Texture.ObjectPlaneS[2] = params[2];
  1025.         ctx->Texture.ObjectPlaneS[3] = params[3];
  1026.      }
  1027.      else if (pname==GL_EYE_PLANE) {
  1028.             /* Transform plane equation by the inverse modelview matrix */
  1029.             if (!ctx->ModelViewInvValid) {
  1030.                gl_compute_modelview_inverse(ctx);
  1031.             }
  1032.             gl_transform_vector( ctx->Texture.EyePlaneS, params,
  1033.                                  ctx->ModelViewInv );
  1034.      }
  1035.      else {
  1036.         gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
  1037.         return;
  1038.      }
  1039.      break;
  1040.       case GL_T:
  1041.          if (pname==GL_TEXTURE_GEN_MODE) {
  1042.         GLenum mode = (GLenum) (GLint) *params;
  1043.         if (mode==GL_OBJECT_LINEAR ||
  1044.         mode==GL_EYE_LINEAR ||
  1045.         mode==GL_SPHERE_MAP) {
  1046.            ctx->Texture.GenModeT = mode;
  1047.         }
  1048.         else {
  1049.            gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
  1050.            return;
  1051.         }
  1052.      }
  1053.      else if (pname==GL_OBJECT_PLANE) {
  1054.         ctx->Texture.ObjectPlaneT[0] = params[0];
  1055.         ctx->Texture.ObjectPlaneT[1] = params[1];
  1056.         ctx->Texture.ObjectPlaneT[2] = params[2];
  1057.         ctx->Texture.ObjectPlaneT[3] = params[3];
  1058.      }
  1059.      else if (pname==GL_EYE_PLANE) {
  1060.             /* Transform plane equation by the inverse modelview matrix */
  1061.             if (!ctx->ModelViewInvValid) {
  1062.                gl_compute_modelview_inverse(ctx);
  1063.             }
  1064.             gl_transform_vector( ctx->Texture.EyePlaneT, params,
  1065.                                  ctx->ModelViewInv );
  1066.      }
  1067.      else {
  1068.         gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
  1069.         return;
  1070.      }
  1071.      break;
  1072.       case GL_R:
  1073.          if (pname==GL_TEXTURE_GEN_MODE) {
  1074.         GLenum mode = (GLenum) (GLint) *params;
  1075.         if (mode==GL_OBJECT_LINEAR ||
  1076.         mode==GL_EYE_LINEAR) {
  1077.            ctx->Texture.GenModeR = mode;
  1078.         }
  1079.         else {
  1080.            gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
  1081.            return;
  1082.         }
  1083.      }
  1084.      else if (pname==GL_OBJECT_PLANE) {
  1085.         ctx->Texture.ObjectPlaneR[0] = params[0];
  1086.         ctx->Texture.ObjectPlaneR[1] = params[1];
  1087.         ctx->Texture.ObjectPlaneR[2] = params[2];
  1088.         ctx->Texture.ObjectPlaneR[3] = params[3];
  1089.      }
  1090.      else if (pname==GL_EYE_PLANE) {
  1091.             /* Transform plane equation by the inverse modelview matrix */
  1092.             if (!ctx->ModelViewInvValid) {
  1093.                gl_compute_modelview_inverse(ctx);
  1094.             }
  1095.             gl_transform_vector( ctx->Texture.EyePlaneR, params,
  1096.                                  ctx->ModelViewInv );
  1097.      }
  1098.      else {
  1099.         gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
  1100.         return;
  1101.      }
  1102.      break;
  1103.       case GL_Q:
  1104.          if (pname==GL_TEXTURE_GEN_MODE) {
  1105.         GLenum mode = (GLenum) (GLint) *params;
  1106.         if (mode==GL_OBJECT_LINEAR ||
  1107.         mode==GL_EYE_LINEAR) {
  1108.            ctx->Texture.GenModeQ = mode;
  1109.         }
  1110.         else {
  1111.            gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
  1112.            return;
  1113.         }
  1114.      }
  1115.      else if (pname==GL_OBJECT_PLANE) {
  1116.         ctx->Texture.ObjectPlaneQ[0] = params[0];
  1117.         ctx->Texture.ObjectPlaneQ[1] = params[1];
  1118.         ctx->Texture.ObjectPlaneQ[2] = params[2];
  1119.         ctx->Texture.ObjectPlaneQ[3] = params[3];
  1120.      }
  1121.      else if (pname==GL_EYE_PLANE) {
  1122.             /* Transform plane equation by the inverse modelview matrix */
  1123.             if (!ctx->ModelViewInvValid) {
  1124.                gl_compute_modelview_inverse(ctx);
  1125.             }
  1126.             gl_transform_vector( ctx->Texture.EyePlaneQ, params,
  1127.                                  ctx->ModelViewInv );
  1128.      }
  1129.      else {
  1130.         gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
  1131.         return;
  1132.      }
  1133.      break;
  1134.       default:
  1135.          gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(coord)" );
  1136.      return;
  1137.    }
  1138.  
  1139.    ctx->NewState |= NEW_TEXTURING;
  1140. }
  1141.  
  1142.  
  1143.  
  1144. void gl_GetTexGendv( GLcontext *ctx,
  1145.                      GLenum coord, GLenum pname, GLdouble *params )
  1146. {
  1147.    if (INSIDE_BEGIN_END(ctx)) {
  1148.       gl_error( ctx, GL_INVALID_OPERATION, "glGetTexGendv" );
  1149.       return;
  1150.    }
  1151.  
  1152.    switch( coord ) {
  1153.       case GL_S:
  1154.          if (pname==GL_TEXTURE_GEN_MODE) {
  1155.             params[0] = ctx->Texture.GenModeS;
  1156.      }
  1157.      else if (pname==GL_OBJECT_PLANE) {
  1158.             COPY_4V( params, ctx->Texture.ObjectPlaneS );
  1159.      }
  1160.      else if (pname==GL_EYE_PLANE) {
  1161.             COPY_4V( params, ctx->Texture.EyePlaneS );
  1162.      }
  1163.      else {
  1164.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
  1165.         return;
  1166.      }
  1167.      break;
  1168.       case GL_T:
  1169.          if (pname==GL_TEXTURE_GEN_MODE) {
  1170.             params[0] = ctx->Texture.GenModeT;
  1171.      }
  1172.      else if (pname==GL_OBJECT_PLANE) {
  1173.             COPY_4V( params, ctx->Texture.ObjectPlaneT );
  1174.      }
  1175.      else if (pname==GL_EYE_PLANE) {
  1176.             COPY_4V( params, ctx->Texture.EyePlaneT );
  1177.      }
  1178.      else {
  1179.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
  1180.         return;
  1181.      }
  1182.      break;
  1183.       case GL_R:
  1184.          if (pname==GL_TEXTURE_GEN_MODE) {
  1185.             params[0] = ctx->Texture.GenModeR;
  1186.      }
  1187.      else if (pname==GL_OBJECT_PLANE) {
  1188.             COPY_4V( params, ctx->Texture.ObjectPlaneR );
  1189.      }
  1190.      else if (pname==GL_EYE_PLANE) {
  1191.             COPY_4V( params, ctx->Texture.EyePlaneR );
  1192.      }
  1193.      else {
  1194.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
  1195.         return;
  1196.      }
  1197.      break;
  1198.       case GL_Q:
  1199.          if (pname==GL_TEXTURE_GEN_MODE) {
  1200.             params[0] = ctx->Texture.GenModeQ;
  1201.      }
  1202.      else if (pname==GL_OBJECT_PLANE) {
  1203.             COPY_4V( params, ctx->Texture.ObjectPlaneQ );
  1204.      }
  1205.      else if (pname==GL_EYE_PLANE) {
  1206.             COPY_4V( params, ctx->Texture.EyePlaneQ );
  1207.      }
  1208.      else {
  1209.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
  1210.         return;
  1211.      }
  1212.      break;
  1213.       default:
  1214.          gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)" );
  1215.      return;
  1216.    }
  1217. }
  1218.  
  1219.  
  1220.  
  1221. void gl_GetTexGenfv( GLcontext *ctx,
  1222.                      GLenum coord, GLenum pname, GLfloat *params )
  1223. {
  1224.    if (INSIDE_BEGIN_END(ctx)) {
  1225.       gl_error( ctx, GL_INVALID_OPERATION, "glGetTexGenfv" );
  1226.       return;
  1227.    }
  1228.  
  1229.    switch( coord ) {
  1230.       case GL_S:
  1231.          if (pname==GL_TEXTURE_GEN_MODE) {
  1232.             params[0] = ctx->Texture.GenModeS;
  1233.      }
  1234.      else if (pname==GL_OBJECT_PLANE) {
  1235.             COPY_4V( params, ctx->Texture.ObjectPlaneS );
  1236.      }
  1237.      else if (pname==GL_EYE_PLANE) {
  1238.             COPY_4V( params, ctx->Texture.EyePlaneS );
  1239.      }
  1240.      else {
  1241.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
  1242.         return;
  1243.      }
  1244.      break;
  1245.       case GL_T:
  1246.          if (pname==GL_TEXTURE_GEN_MODE) {
  1247.             params[0] = ctx->Texture.GenModeT;
  1248.      }
  1249.      else if (pname==GL_OBJECT_PLANE) {
  1250.             COPY_4V( params, ctx->Texture.ObjectPlaneT );
  1251.      }
  1252.      else if (pname==GL_EYE_PLANE) {
  1253.             COPY_4V( params, ctx->Texture.EyePlaneT );
  1254.      }
  1255.      else {
  1256.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
  1257.         return;
  1258.      }
  1259.      break;
  1260.       case GL_R:
  1261.          if (pname==GL_TEXTURE_GEN_MODE) {
  1262.             params[0] = ctx->Texture.GenModeR;
  1263.      }
  1264.      else if (pname==GL_OBJECT_PLANE) {
  1265.             COPY_4V( params, ctx->Texture.ObjectPlaneR );
  1266.      }
  1267.      else if (pname==GL_EYE_PLANE) {
  1268.             COPY_4V( params, ctx->Texture.EyePlaneR );
  1269.      }
  1270.      else {
  1271.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
  1272.         return;
  1273.      }
  1274.      break;
  1275.       case GL_Q:
  1276.          if (pname==GL_TEXTURE_GEN_MODE) {
  1277.             params[0] = ctx->Texture.GenModeQ;
  1278.      }
  1279.      else if (pname==GL_OBJECT_PLANE) {
  1280.             COPY_4V( params, ctx->Texture.ObjectPlaneQ );
  1281.      }
  1282.      else if (pname==GL_EYE_PLANE) {
  1283.             COPY_4V( params, ctx->Texture.EyePlaneQ );
  1284.      }
  1285.      else {
  1286.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
  1287.         return;
  1288.      }
  1289.      break;
  1290.       default:
  1291.          gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)" );
  1292.      return;
  1293.    }
  1294. }
  1295.  
  1296.  
  1297.  
  1298. void gl_GetTexGeniv( GLcontext *ctx,
  1299.                      GLenum coord, GLenum pname, GLint *params )
  1300. {
  1301.    if (INSIDE_BEGIN_END(ctx)) {
  1302.       gl_error( ctx, GL_INVALID_OPERATION, "glGetTexGeniv" );
  1303.       return;
  1304.    }
  1305.  
  1306.    switch( coord ) {
  1307.       case GL_S:
  1308.          if (pname==GL_TEXTURE_GEN_MODE) {
  1309.             params[0] = ctx->Texture.GenModeS;
  1310.      }
  1311.      else if (pname==GL_OBJECT_PLANE) {
  1312.             COPY_4V( params, ctx->Texture.ObjectPlaneS );
  1313.      }
  1314.      else if (pname==GL_EYE_PLANE) {
  1315.             COPY_4V( params, ctx->Texture.EyePlaneS );
  1316.      }
  1317.      else {
  1318.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
  1319.         return;
  1320.      }
  1321.      break;
  1322.       case GL_T:
  1323.          if (pname==GL_TEXTURE_GEN_MODE) {
  1324.             params[0] = ctx->Texture.GenModeT;
  1325.      }
  1326.      else if (pname==GL_OBJECT_PLANE) {
  1327.             COPY_4V( params, ctx->Texture.ObjectPlaneT );
  1328.      }
  1329.      else if (pname==GL_EYE_PLANE) {
  1330.             COPY_4V( params, ctx->Texture.EyePlaneT );
  1331.      }
  1332.      else {
  1333.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
  1334.         return;
  1335.      }
  1336.      break;
  1337.       case GL_R:
  1338.          if (pname==GL_TEXTURE_GEN_MODE) {
  1339.             params[0] = ctx->Texture.GenModeR;
  1340.      }
  1341.      else if (pname==GL_OBJECT_PLANE) {
  1342.             COPY_4V( params, ctx->Texture.ObjectPlaneR );
  1343.      }
  1344.      else if (pname==GL_EYE_PLANE) {
  1345.             COPY_4V( params, ctx->Texture.EyePlaneR );
  1346.      }
  1347.      else {
  1348.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
  1349.         return;
  1350.      }
  1351.      break;
  1352.       case GL_Q:
  1353.          if (pname==GL_TEXTURE_GEN_MODE) {
  1354.             params[0] = ctx->Texture.GenModeQ;
  1355.      }
  1356.      else if (pname==GL_OBJECT_PLANE) {
  1357.             COPY_4V( params, ctx->Texture.ObjectPlaneQ );
  1358.      }
  1359.      else if (pname==GL_EYE_PLANE) {
  1360.             COPY_4V( params, ctx->Texture.EyePlaneQ );
  1361.      }
  1362.      else {
  1363.         gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
  1364.         return;
  1365.      }
  1366.      break;
  1367.       default:
  1368.          gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)" );
  1369.      return;
  1370.    }
  1371. }
  1372.  
  1373.  
  1374.  
  1375. /*
  1376.  * Perform automatic texture coordinate generation.
  1377.  * Input:  ctx - the context
  1378.  *         n - number of texture coordinates to generate
  1379.  *         obj - array of vertexes in object coordinate system
  1380.  *         eye - array of vertexes in eye coordinate system
  1381.  *         normal - array of normal vectores in eye coordinate system
  1382.  * Output:  texcoord - array of resuling texture coordinates
  1383.  */
  1384. void gl_texgen( GLcontext *ctx, GLint n,
  1385.                 GLfloat obj[][4], GLfloat eye[][4],
  1386.                 GLfloat normal[][3], GLfloat texcoord[][4] )
  1387. {
  1388.    /* special case: S and T sphere mapping */
  1389.    if (ctx->Texture.TexGenEnabled==(S_BIT|T_BIT)
  1390.        && ctx->Texture.GenModeS==GL_SPHERE_MAP
  1391.        && ctx->Texture.GenModeT==GL_SPHERE_MAP) {
  1392.       GLint i;
  1393.       for (i=0;i<n;i++) {
  1394.          GLfloat u[3], two_nn, m, fx, fy, fz;
  1395.          COPY_3V( u, eye[i] );
  1396.          NORMALIZE_3V( u );
  1397.          two_nn = 2.0F * DOT3(normal[i],normal[i]);
  1398.          fx = u[0] - two_nn * u[0];
  1399.          fy = u[1] - two_nn * u[1];
  1400.          fz = u[2] - two_nn * u[2];
  1401.          m = 2.0F * sqrt( fx*fx + fy*fy + (fz+1.0F)*(fz+1.0F) );
  1402.          if (m==0.0F) {
  1403.             texcoord[i][0] = 0.5F;
  1404.             texcoord[i][1] = 0.5F;
  1405.          }
  1406.          else {
  1407.             GLfloat mInv = 1.0F / m;
  1408.             texcoord[i][0] = fx * mInv + 0.5F;
  1409.             texcoord[i][1] = fy * mInv + 0.5F;
  1410.          }
  1411.       }
  1412.       return;
  1413.    }
  1414.  
  1415.    /* general solution */
  1416.    if (ctx->Texture.TexGenEnabled & S_BIT) {
  1417.       GLint i;
  1418.       switch (ctx->Texture.GenModeS) {
  1419.      case GL_OBJECT_LINEAR:
  1420.             for (i=0;i<n;i++) {
  1421.                texcoord[i][0] = DOT4( obj[i], ctx->Texture.ObjectPlaneS );
  1422.             }
  1423.         break;
  1424.      case GL_EYE_LINEAR:
  1425.             for (i=0;i<n;i++) {
  1426.                texcoord[i][0] = DOT4( eye[i], ctx->Texture.EyePlaneS );
  1427.             }
  1428.         break;
  1429.      case GL_SPHERE_MAP:
  1430.             for (i=0;i<n;i++) {
  1431.                GLfloat u[3], two_nn, m, fx, fy, fz;
  1432.                COPY_3V( u, eye[i] );
  1433.                NORMALIZE_3V( u );
  1434.                two_nn = 2.0*DOT3(normal[i],normal[i]);
  1435.                fx = u[0] - two_nn * u[0];
  1436.                fy = u[1] - two_nn * u[1];
  1437.                fz = u[2] - two_nn * u[2];
  1438.                m = 2.0 * sqrt( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  1439.                if (m==0.0) {
  1440.                   texcoord[i][0] = 0.0;
  1441.                }
  1442.                else {
  1443.                   texcoord[i][0] = fx / m + 0.5;
  1444.                }
  1445.             }
  1446.         break;
  1447.          default:
  1448.             abort();
  1449.       }
  1450.    }
  1451.  
  1452.    if (ctx->Texture.TexGenEnabled & T_BIT) {
  1453.       GLint i;
  1454.       switch (ctx->Texture.GenModeT) {
  1455.      case GL_OBJECT_LINEAR:
  1456.             for (i=0;i<n;i++) {
  1457.                texcoord[i][1] = DOT4( obj[i], ctx->Texture.ObjectPlaneT );
  1458.             }
  1459.         break;
  1460.      case GL_EYE_LINEAR:
  1461.             for (i=0;i<n;i++) {
  1462.                texcoord[i][1] = DOT4( eye[i], ctx->Texture.EyePlaneT );
  1463.             }
  1464.         break;
  1465.      case GL_SPHERE_MAP:
  1466.         /* TODO: safe to assume that m and fy valid from above??? */
  1467.             for (i=0;i<n;i++) {
  1468.                GLfloat u[3], two_nn, m, fx, fy, fz;
  1469.                COPY_3V( u, eye[i] );
  1470.                NORMALIZE_3V( u );
  1471.                two_nn = 2.0*DOT3(normal[i],normal[i]);
  1472.                fx = u[0] - two_nn * u[0];
  1473.                fy = u[1] - two_nn * u[1];
  1474.                fz = u[2] - two_nn * u[2];
  1475.                m = 2.0 * sqrt( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  1476.                if (m==0.0) {
  1477.                   texcoord[i][1] = 0.0;
  1478.                }
  1479.                else {
  1480.                   texcoord[i][1] = fy / m + 0.5;
  1481.                }
  1482.             }
  1483.         break;
  1484.          default:
  1485.             abort();
  1486.       }
  1487.    }
  1488.  
  1489.    if (ctx->Texture.TexGenEnabled & R_BIT) {
  1490.       GLint i;
  1491.       switch (ctx->Texture.GenModeR) {
  1492.      case GL_OBJECT_LINEAR:
  1493.             for (i=0;i<n;i++) {
  1494.                texcoord[i][2] = DOT4( obj[i], ctx->Texture.ObjectPlaneR );
  1495.             }
  1496.         break;
  1497.      case GL_EYE_LINEAR:
  1498.             for (i=0;i<n;i++) {
  1499.                texcoord[i][2] = DOT4( eye[i], ctx->Texture.EyePlaneR );
  1500.             }
  1501.         break;
  1502.          default:
  1503.             abort();
  1504.       }
  1505.    }
  1506.  
  1507.    if (ctx->Texture.TexGenEnabled & Q_BIT) {
  1508.       GLint i;
  1509.       switch (ctx->Texture.GenModeQ) {
  1510.      case GL_OBJECT_LINEAR:
  1511.             for (i=0;i<n;i++) {
  1512.                texcoord[i][3] = DOT4( obj[i], ctx->Texture.ObjectPlaneQ );
  1513.             }
  1514.         break;
  1515.      case GL_EYE_LINEAR:
  1516.             for (i=0;i<n;i++) {
  1517.                texcoord[i][3] = DOT4( eye[i], ctx->Texture.EyePlaneQ );
  1518.             }
  1519.         break;
  1520.          default:
  1521.             abort();
  1522.       }
  1523.    }
  1524. }
  1525.  
  1526.  
  1527.  
  1528.  
  1529.  
  1530. /**********************************************************************/
  1531. /*                    1-D Texture Sampling Functions                  */
  1532. /**********************************************************************/
  1533.  
  1534.  
  1535. /*
  1536.  * Return the fractional part of x.
  1537.  */
  1538. #define frac(x) ((GLfloat)(x)-floor((GLfloat)x))
  1539.  
  1540.  
  1541.  
  1542. /*
  1543.  * Given 1-D texture image and an (i) texel column coordinate, return the
  1544.  * texel color.
  1545.  */
  1546. static void get_1d_texel( struct gl_texture_image *img, GLint i,
  1547.                           GLubyte *red, GLubyte *green, GLubyte *blue,
  1548.                           GLubyte *alpha )
  1549. {
  1550.    GLubyte *texel;
  1551.  
  1552.    /* DEBUG */
  1553.    GLint width = img->Width;
  1554.    if (i<0 || i>=width)  abort();
  1555.  
  1556.    switch (img->Format) {
  1557.       case GL_ALPHA:
  1558.          *alpha = img->Data[ i ];
  1559.          return;
  1560.       case GL_LUMINANCE:
  1561.       case GL_INTENSITY:
  1562.          *red   = img->Data[ i ];
  1563.          return;
  1564.       case GL_LUMINANCE_ALPHA:
  1565.          texel = img->Data + i * 2;
  1566.          *red   = texel[0];
  1567.          *alpha = texel[1];
  1568.          return;
  1569.       case GL_RGB:
  1570.          texel = img->Data + i * 3;
  1571.          *red   = texel[0];
  1572.          *green = texel[1];
  1573.          *blue  = texel[2];
  1574.          return;
  1575.       case GL_RGBA:
  1576.          texel = img->Data + i * 4;
  1577.          *red   = texel[0];
  1578.          *green = texel[1];
  1579.          *blue  = texel[2];
  1580.          *alpha = texel[3];
  1581.          return;
  1582.       default:
  1583.          abort();
  1584.    }
  1585. }
  1586.  
  1587.  
  1588.  
  1589. /*
  1590.  * Return the texture sample for coordinate (s) using GL_NEAREST filter.
  1591.  */
  1592. static void sample_1d_nearest( GLcontext *ctx,
  1593.                                struct gl_texture_image *img,
  1594.                                GLfloat s,
  1595.                                GLubyte *red, GLubyte *green,
  1596.                                GLubyte *blue, GLubyte *alpha )
  1597. {
  1598.    GLint width = img->Width2;  /* without border, power of two */
  1599.    GLint i;
  1600.    GLubyte *texel;
  1601.  
  1602.    /* Clamp/Repeat S and convert to integer texel coordinate */
  1603.    if (ctx->Texture.Current1D->WrapS==GL_REPEAT) {
  1604.       /* s limited to [0,1) */
  1605.       /* i limited to [0,width-1] */
  1606.       i = (GLint) (s * width);
  1607.       i &= (width-1);
  1608.    }
  1609.    else {
  1610.       /* s limited to [0,1] */
  1611.       /* i limited to [0,width-1] */
  1612.       if (s<0.0F)        i = 0;
  1613.       else if (s>1.0F)   i = width-1;
  1614.       else               i = (GLint) (s * width);
  1615.    }
  1616.  
  1617.    /* skip over the border, if any */
  1618.    i += img->Border;
  1619.  
  1620.    /* Get the texel */
  1621.    switch (img->Format) {
  1622.       case GL_ALPHA:
  1623.          *alpha = img->Data[i];
  1624.          return;
  1625.       case GL_LUMINANCE:
  1626.       case GL_INTENSITY:
  1627.          *red   = img->Data[i];
  1628.          return;
  1629.       case GL_LUMINANCE_ALPHA:
  1630.          texel = img->Data + i * 2;
  1631.          *red   = texel[0];
  1632.          *alpha = texel[1];
  1633.          return;
  1634.       case GL_RGB:
  1635.          texel = img->Data + i * 3;
  1636.          *red   = texel[0];
  1637.          *green = texel[1];
  1638.          *blue  = texel[2];
  1639.          return;
  1640.       case GL_RGBA:
  1641.          texel = img->Data + i * 4;
  1642.          *red   = texel[0];
  1643.          *green = texel[1];
  1644.          *blue  = texel[2];
  1645.          *alpha = texel[3];
  1646.          return;
  1647.       default:
  1648.          abort();
  1649.    }
  1650. }
  1651.  
  1652.  
  1653.  
  1654. /*
  1655.  * Return the texture sample for coordinate (s) using GL_LINEAR filter.
  1656.  */
  1657. static void sample_1d_linear( GLcontext *ctx,
  1658.                               struct gl_texture_image *img,
  1659.                               GLfloat s,
  1660.                               GLubyte *red, GLubyte *green,
  1661.                               GLubyte *blue, GLubyte *alpha )
  1662. {
  1663.    GLint width = img->Width2;
  1664.    GLint i0, i1;
  1665.    GLfloat u;
  1666.    GLint i0border, i1border;
  1667.  
  1668.    u = s * width;
  1669.    if (ctx->Texture.Current1D->WrapS==GL_REPEAT) {
  1670.       i0 = ((GLint) floor(u - 0.5F)) % width;
  1671.       i1 = (i0 + 1) & (width-1);
  1672.       i0border = i1border = 0;
  1673.    }
  1674.    else {
  1675.       i0 = (GLint) floor(u - 0.5F);
  1676.       i1 = i0 + 1;
  1677.       i0border = (i0<0) | (i0>=width);
  1678.       i1border = (i1<0) | (i1>=width);
  1679.    }
  1680.  
  1681.    if (img->Border) {
  1682.       i0 += img->Border;
  1683.       i1 += img->Border;
  1684.       i0border = i1border = 0;
  1685.    }
  1686.    else {
  1687.       i0 &= (width-1);
  1688.    }
  1689.  
  1690.    {
  1691.       GLfloat a = frac(u - 0.5F);
  1692.  
  1693.       GLint w0 = (GLint) ((1.0F-a) * 256.0F);
  1694.       GLint w1 = (GLint) (      a  * 256.0F);
  1695.  
  1696.       GLubyte red0, green0, blue0, alpha0;
  1697.       GLubyte red1, green1, blue1, alpha1;
  1698.  
  1699.       if (i0border) {
  1700.          red0   = ctx->Texture.Current1D->BorderColor[0];
  1701.          green0 = ctx->Texture.Current1D->BorderColor[1];
  1702.          blue0  = ctx->Texture.Current1D->BorderColor[2];
  1703.          alpha0 = ctx->Texture.Current1D->BorderColor[3];
  1704.       }
  1705.       else {
  1706.          get_1d_texel( img, i0, &red0, &green0, &blue0, &alpha0 );
  1707.       }
  1708.       if (i1border) {
  1709.          red1   = ctx->Texture.Current1D->BorderColor[0];
  1710.          green1 = ctx->Texture.Current1D->BorderColor[1];
  1711.          blue1  = ctx->Texture.Current1D->BorderColor[2];
  1712.          alpha1 = ctx->Texture.Current1D->BorderColor[3];
  1713.       }
  1714.       else {
  1715.          get_1d_texel( img, i1, &red1, &green1, &blue1, &alpha1 );
  1716.       }
  1717.  
  1718.       *red   = (w0*red0   + w1*red1)   >> 8;
  1719.       *green = (w0*green0 + w1*green1) >> 8;
  1720.       *blue  = (w0*blue0  + w1*blue1)  >> 8;
  1721.       *alpha = (w0*alpha0 + w1*alpha1) >> 8;
  1722.    }
  1723. }
  1724.  
  1725.  
  1726. static void sample_1d_nearest_mipmap_nearest( GLcontext *ctx,
  1727.                                               GLfloat lambda, GLfloat s,
  1728.                                               GLubyte *red, GLubyte *green,
  1729.                                               GLubyte *blue, GLubyte *alpha )
  1730. {
  1731.    GLint level;
  1732.    if (lambda<=0.5F) {
  1733.       level = 0;
  1734.    }
  1735.    else {
  1736.       GLint widthlog2 = ctx->Texture.Current1D->Image[0]->WidthLog2;
  1737.       level = (GLint) (lambda + 0.499999F);
  1738.       if (level>widthlog2 ) {
  1739.          level = widthlog2;
  1740.       }
  1741.    }
  1742.    sample_1d_nearest( ctx, ctx->Texture.Current1D->Image[level],
  1743.                       s, red, green, blue, alpha );
  1744. }
  1745.  
  1746.  
  1747. static void sample_1d_linear_mipmap_nearest( GLcontext *ctx,
  1748.                                              GLfloat lambda, GLfloat s,
  1749.                                              GLubyte *red, GLubyte *green,
  1750.                                              GLubyte *blue, GLubyte *alpha )
  1751. {
  1752.    GLint level;
  1753.    if (lambda<=0.5F) {
  1754.       level = 0;
  1755.    }
  1756.    else {
  1757.       GLint widthlog2 = ctx->Texture.Current1D->Image[0]->WidthLog2;
  1758.       level = (GLint) (lambda + 0.499999F);
  1759.       if (level>widthlog2 ) {
  1760.          level = widthlog2;
  1761.       }
  1762.    }
  1763.    sample_1d_linear( ctx, ctx->Texture.Current1D->Image[level],
  1764.                      s, red, green, blue, alpha );
  1765. }
  1766.  
  1767.  
  1768.  
  1769. static void sample_1d_nearest_mipmap_linear( GLcontext *ctx,
  1770.                                              GLfloat lambda, GLfloat s,
  1771.                                              GLubyte *red, GLubyte *green,
  1772.                                              GLubyte *blue, GLubyte *alpha )
  1773. {
  1774.    GLint max = ctx->Texture.Current1D->Image[0]->MaxLog2;
  1775.  
  1776.    if (lambda>=max) {
  1777.       sample_1d_nearest( ctx, ctx->Texture.Current1D->Image[max],
  1778.                          s, red, green, blue, alpha );
  1779.    }
  1780.    else {
  1781.       GLubyte red0, green0, blue0, alpha0;
  1782.       GLubyte red1, green1, blue1, alpha1;
  1783.       GLfloat f = frac(lambda);
  1784.       GLint level = (GLint) (lambda + 1.0F);
  1785.       level = CLAMP( level, 1, max );
  1786.       sample_1d_nearest( ctx, ctx->Texture.Current1D->Image[level-1],
  1787.                          s, &red0, &green0, &blue0, &alpha0 );
  1788.       sample_1d_nearest( ctx, ctx->Texture.Current1D->Image[level],
  1789.                          s, &red1, &green1, &blue1, &alpha1 );
  1790.       *red   = (1.0F-f)*red0   + f*red1;
  1791.       *green = (1.0F-f)*green0 + f*green1;
  1792.       *blue  = (1.0F-f)*blue0  + f*blue1;
  1793.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  1794.    }
  1795. }
  1796.  
  1797.  
  1798.  
  1799. static void sample_1d_linear_mipmap_linear( GLcontext *ctx,
  1800.                                             GLfloat lambda, GLfloat s,
  1801.                                             GLubyte *red, GLubyte *green,
  1802.                                             GLubyte *blue, GLubyte *alpha )
  1803. {
  1804.    GLint max = ctx->Texture.Current1D->Image[0]->MaxLog2;
  1805.  
  1806.    if (lambda>=max) {
  1807.       sample_1d_linear( ctx, ctx->Texture.Current1D->Image[max],
  1808.                         s, red, green, blue, alpha );
  1809.    }
  1810.    else {
  1811.       GLubyte red0, green0, blue0, alpha0;
  1812.       GLubyte red1, green1, blue1, alpha1;
  1813.       GLfloat f = frac(lambda);
  1814.       GLint level = (GLint) (lambda + 1.0F);
  1815.       level = CLAMP( level, 1, max );
  1816.       sample_1d_linear( ctx, ctx->Texture.Current1D->Image[level-1],
  1817.                         s, &red0, &green0, &blue0, &alpha0 );
  1818.       sample_1d_linear( ctx, ctx->Texture.Current1D->Image[level],
  1819.                         s, &red1, &green1, &blue1, &alpha1 );
  1820.       *red   = (1.0F-f)*red0   + f*red1;
  1821.       *green = (1.0F-f)*green0 + f*green1;
  1822.       *blue  = (1.0F-f)*blue0  + f*blue1;
  1823.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  1824.    }
  1825. }
  1826.  
  1827.  
  1828.  
  1829. /*
  1830.  * Given an (s) texture coordinate and lambda (level of detail) value,
  1831.  * return a texture sample.
  1832.  *
  1833.  */
  1834. static void sample_1d_texture( GLcontext *ctx,
  1835.                                GLfloat s, GLfloat lambda,
  1836.                                GLubyte *red, GLubyte *green, GLubyte *blue,
  1837.                                GLubyte *alpha, GLfloat c )
  1838. {
  1839.    GLint level;
  1840.  
  1841.    if (lambda>c) {
  1842.       /* minification */
  1843.       switch (ctx->Texture.Current1D->MinFilter) {
  1844.          case GL_NEAREST:
  1845.             level = 0;
  1846.             sample_1d_nearest( ctx, ctx->Texture.Current1D->Image[level],
  1847.                                s, red, green, blue, alpha );
  1848.             break;
  1849.          case GL_LINEAR:
  1850.             level = 0;
  1851.             sample_1d_linear( ctx, ctx->Texture.Current1D->Image[level],
  1852.                               s, red, green, blue, alpha );
  1853.             break;
  1854.          case GL_NEAREST_MIPMAP_NEAREST:
  1855.         sample_1d_nearest_mipmap_nearest( ctx, lambda, s,
  1856.                                               red, green, blue, alpha );
  1857.             break;
  1858.          case GL_LINEAR_MIPMAP_NEAREST:
  1859.         sample_1d_linear_mipmap_nearest( ctx, lambda, s,
  1860.                                              red, green, blue, alpha );
  1861.             break;
  1862.          case GL_NEAREST_MIPMAP_LINEAR:
  1863.         sample_1d_nearest_mipmap_linear( ctx, lambda, s,
  1864.                                              red, green, blue, alpha );
  1865.             break;
  1866.          case GL_LINEAR_MIPMAP_LINEAR:
  1867.         sample_1d_linear_mipmap_linear( ctx, lambda, s,
  1868.                                             red, green, blue, alpha );
  1869.             break;
  1870.          default:
  1871.             abort();
  1872.       }
  1873.    }
  1874.    else {
  1875.       /* magnification */
  1876.       switch (ctx->Texture.Current1D->MagFilter) {
  1877.          case GL_NEAREST:
  1878.             sample_1d_nearest( ctx, ctx->Texture.Current1D->Image[0],
  1879.                                s, red, green, blue, alpha );
  1880.             break;
  1881.          case GL_LINEAR:
  1882.             sample_1d_linear( ctx, ctx->Texture.Current1D->Image[0],
  1883.                               s, red, green, blue, alpha );
  1884.             break;
  1885.          default:
  1886.             abort();
  1887.       }
  1888.    }
  1889. }
  1890.  
  1891.  
  1892.  
  1893. /**********************************************************************/
  1894. /*                    2-D Texture Sampling Functions                  */
  1895. /**********************************************************************/
  1896.  
  1897.  
  1898. /*
  1899.  * Given a texture image and an (i,j) integer texel coordinate, return the
  1900.  * texel color.
  1901.  */
  1902. static void get_2d_texel( struct gl_texture_image *img, GLint i, GLint j,
  1903.                           GLubyte *red, GLubyte *green, GLubyte *blue,
  1904.                           GLubyte *alpha )
  1905. {
  1906.    GLint width = img->Width;    /* includes border */
  1907.    GLubyte *texel;
  1908.  
  1909. #ifdef DEBUG
  1910.    GLint height = img->Height;  /* includes border */
  1911.    if (i<0 || i>=width)  abort();
  1912.    if (j<0 || j>=height)  abort();
  1913. #endif
  1914.  
  1915.    switch (img->Format) {
  1916.       case GL_ALPHA:
  1917.          *alpha = img->Data[ width * j + i ];
  1918.          return;
  1919.       case GL_LUMINANCE:
  1920.       case GL_INTENSITY:
  1921.          *red   = img->Data[ width * j + i ];
  1922.          return;
  1923.       case GL_LUMINANCE_ALPHA:
  1924.          texel = img->Data + (width * j + i) * 2;
  1925.          *red   = texel[0];
  1926.          *alpha = texel[1];
  1927.          return;
  1928.       case GL_RGB:
  1929.          texel = img->Data + (width * j + i) * 3;
  1930.          *red   = texel[0];
  1931.          *green = texel[1];
  1932.          *blue  = texel[2];
  1933.          return;
  1934.       case GL_RGBA:
  1935.          texel = img->Data + (width * j + i) * 4;
  1936.          *red   = texel[0];
  1937.          *green = texel[1];
  1938.          *blue  = texel[2];
  1939.          *alpha = texel[3];
  1940.          return;
  1941.       default:
  1942.          abort();
  1943.    }
  1944. }
  1945.  
  1946.  
  1947.  
  1948. /*
  1949.  * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
  1950.  */
  1951. static void sample_2d_nearest( GLcontext *ctx,
  1952.                                struct gl_texture_image *img,
  1953.                                GLfloat s, GLfloat t,
  1954.                                GLubyte *red, GLubyte *green,
  1955.                                GLubyte *blue, GLubyte *alpha )
  1956. {
  1957.    GLint imgWidth = img->Width;  /* includes border */
  1958.    GLint width = img->Width2;    /* without border, power of two */
  1959.    GLint height = img->Height2;  /* without border, power of two */
  1960.    GLint i, j;
  1961.    GLubyte *texel;
  1962.  
  1963.    /* Clamp/Repeat S and convert to integer texel coordinate */
  1964.    if (ctx->Texture.Current2D->WrapS==GL_REPEAT) {
  1965.       /* s limited to [0,1) */
  1966.       /* i limited to [0,width-1] */
  1967.       i = (GLint) (s * width);
  1968.       i &= (width-1);
  1969.    }
  1970.    else {
  1971.       /* s limited to [0,1] */
  1972.       /* i limited to [0,width-1] */
  1973.       if (s<=0.0F)      i = 0;
  1974.       else if (s>1.0F)  i = width-1;
  1975.       else              i = (GLint) (s * width);
  1976.    }
  1977.  
  1978.    /* Clamp/Repeat T and convert to integer texel coordinate */
  1979.    if (ctx->Texture.Current2D->WrapT==GL_REPEAT) {
  1980.       /* t limited to [0,1) */
  1981.       /* j limited to [0,height-1] */
  1982.       j = (GLint) (t * height);
  1983.       j &= (height-1);
  1984.    }
  1985.    else {
  1986.       /* t limited to [0,1] */
  1987.       /* j limited to [0,height-1] */
  1988.       if (t<=0.0F)      j = 0;
  1989.       else if (t>1.0F)  j = height-1;
  1990.       else              j = (GLint) (t * height);
  1991.    }
  1992.  
  1993.    /* skip over the border, if any */
  1994.    i += img->Border;
  1995.    j += img->Border;
  1996.  
  1997.    switch (img->Format) {
  1998.       case GL_ALPHA:
  1999.          *alpha = img->Data[ j * imgWidth + i ];
  2000.          return;
  2001.       case GL_LUMINANCE:
  2002.       case GL_INTENSITY:
  2003.          *red   = img->Data[ j * imgWidth + i ];
  2004.          return;
  2005.       case GL_LUMINANCE_ALPHA:
  2006.          texel = img->Data + ((j * imgWidth + i) << 1);
  2007.          *red   = texel[0];
  2008.          *alpha = texel[1];
  2009.          return;
  2010.       case GL_RGB:
  2011.          texel = img->Data + (j * imgWidth + i) * 3;
  2012.          *red   = texel[0];
  2013.          *green = texel[1];
  2014.          *blue  = texel[2];
  2015.          return;
  2016.       case GL_RGBA:
  2017.          texel = img->Data + ((j * imgWidth + i) << 2);
  2018.          *red   = texel[0];
  2019.          *green = texel[1];
  2020.          *blue  = texel[2];
  2021.          *alpha = texel[3];
  2022.          return;
  2023.       default:
  2024.          abort();
  2025.    }
  2026. }
  2027.  
  2028.  
  2029.  
  2030. /*
  2031.  * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
  2032.  */
  2033. static void sample_2d_linear( GLcontext *ctx,
  2034.                               struct gl_texture_image *img,
  2035.                               GLfloat s, GLfloat t,
  2036.                               GLubyte *red, GLubyte *green,
  2037.                               GLubyte *blue, GLubyte *alpha )
  2038. {
  2039.    GLint width = img->Width2;
  2040.    GLint height = img->Height2;
  2041.    GLint i0, j0, i1, j1;
  2042.    GLint i0border, j0border, i1border, j1border;
  2043.    GLfloat u, v;
  2044.  
  2045.    u = s * width;
  2046.    if (ctx->Texture.Current2D->WrapS==GL_REPEAT) {
  2047.       i0 = ((GLint) floor(u - 0.5F)) % width;
  2048.       i1 = (i0 + 1) & (width-1);
  2049.       i0border = i1border = 0;
  2050.    }
  2051.    else {
  2052.       i0 = (GLint) floor(u - 0.5F);
  2053.       i1 = i0 + 1;
  2054.       i0border = (i0<0) | (i0>=width);
  2055.       i1border = (i1<0) | (i1>=width);
  2056.    }
  2057.  
  2058.    v = t * height;
  2059.    if (ctx->Texture.Current2D->WrapT==GL_REPEAT) {
  2060.       j0 = ((GLint) floor(v - 0.5F)) % height;
  2061.       j1 = (j0 + 1) & (height-1);
  2062.       j0border = j1border = 0;
  2063.    }
  2064.    else {
  2065.       j0 = (GLint) floor(v - 0.5F );
  2066.       j1 = j0 + 1;
  2067.       j0border = (j0<0) | (j0>=height);
  2068.       j1border = (j1<0) | (j1>=height);
  2069.    }
  2070.  
  2071.    if (img->Border) {
  2072.       i0 += img->Border;
  2073.       i1 += img->Border;
  2074.       j0 += img->Border;
  2075.       j1 += img->Border;
  2076.       i0border = i1border = 0;
  2077.       j0border = j1border = 0;
  2078.    }
  2079.    else {
  2080.       i0 &= (width-1);
  2081.       j0 &= (height-1);
  2082.    }
  2083.  
  2084.    {
  2085.       GLfloat a = frac(u - 0.5F);
  2086.       GLfloat b = frac(v - 0.5F);
  2087.  
  2088.       GLint w00 = (GLint) ((1.0F-a)*(1.0F-b) * 256.0F);
  2089.       GLint w10 = (GLint) (      a *(1.0F-b) * 256.0F);
  2090.       GLint w01 = (GLint) ((1.0F-a)*      b  * 256.0F);
  2091.       GLint w11 = (GLint) (      a *      b  * 256.0F);
  2092.  
  2093.       GLubyte red00, green00, blue00, alpha00;
  2094.       GLubyte red10, green10, blue10, alpha10;
  2095.       GLubyte red01, green01, blue01, alpha01;
  2096.       GLubyte red11, green11, blue11, alpha11;
  2097.  
  2098.       if (i0border | j0border) {
  2099.          red00   = ctx->Texture.Current2D->BorderColor[0];
  2100.          green00 = ctx->Texture.Current2D->BorderColor[1];
  2101.          blue00  = ctx->Texture.Current2D->BorderColor[2];
  2102.          alpha00 = ctx->Texture.Current2D->BorderColor[3];
  2103.       }
  2104.       else {
  2105.          get_2d_texel( img, i0, j0, &red00, &green00, &blue00, &alpha00 );
  2106.       }
  2107.       if (i1border | j0border) {
  2108.          red10   = ctx->Texture.Current2D->BorderColor[0];
  2109.          green10 = ctx->Texture.Current2D->BorderColor[1];
  2110.          blue10  = ctx->Texture.Current2D->BorderColor[2];
  2111.          alpha10 = ctx->Texture.Current2D->BorderColor[3];
  2112.       }
  2113.       else {
  2114.          get_2d_texel( img, i1, j0, &red10, &green10, &blue10, &alpha10 );
  2115.       }
  2116.       if (i0border | j1border) {
  2117.          red01   = ctx->Texture.Current2D->BorderColor[0];
  2118.          green01 = ctx->Texture.Current2D->BorderColor[1];
  2119.          blue01  = ctx->Texture.Current2D->BorderColor[2];
  2120.          alpha01 = ctx->Texture.Current2D->BorderColor[3];
  2121.       }
  2122.       else {
  2123.          get_2d_texel( img, i0, j1, &red01, &green01, &blue01, &alpha01 );
  2124.       }
  2125.       if (i1border | j1border) {
  2126.          red11   = ctx->Texture.Current2D->BorderColor[0];
  2127.          green11 = ctx->Texture.Current2D->BorderColor[1];
  2128.          blue11  = ctx->Texture.Current2D->BorderColor[2];
  2129.          alpha11 = ctx->Texture.Current2D->BorderColor[3];
  2130.       }
  2131.       else {
  2132.          get_2d_texel( img, i1, j1, &red11, &green11, &blue11, &alpha11 );
  2133.       }
  2134.  
  2135.       *red   = (w00*red00   + w10*red10   + w01*red01   + w11*red11  ) >> 8;
  2136.       *green = (w00*green00 + w10*green10 + w01*green01 + w11*green11) >> 8;
  2137.       *blue  = (w00*blue00  + w10*blue10  + w01*blue01  + w11*blue11 ) >> 8;
  2138.       *alpha = (w00*alpha00 + w10*alpha10 + w01*alpha01 + w11*alpha11) >> 8;
  2139.    }
  2140. }
  2141.  
  2142.  
  2143.  
  2144. static void sample_2d_nearest_mipmap_nearest( GLcontext *ctx,
  2145.                                               GLfloat lambda,
  2146.                                               GLfloat s, GLfloat t,
  2147.                                               GLubyte *red, GLubyte *green,
  2148.                                               GLubyte *blue, GLubyte *alpha )
  2149. {
  2150.    GLint level;
  2151.    if (lambda<=0.5F) {
  2152.       level = 0;
  2153.    }
  2154.    else {
  2155.       GLint max = ctx->Texture.Current2D->Image[0]->MaxLog2;
  2156.       level = (GLint) (lambda + 0.499999F);
  2157.       if (level>max) {
  2158.          level = max;
  2159.       }
  2160.    }
  2161.    sample_2d_nearest( ctx, ctx->Texture.Current2D->Image[level],
  2162.                       s, t, red, green, blue, alpha );
  2163. }
  2164.  
  2165.  
  2166.  
  2167. static void sample_2d_linear_mipmap_nearest( GLcontext *ctx,
  2168.                                              GLfloat lambda,
  2169.                                              GLfloat s, GLfloat t,
  2170.                                              GLubyte *red, GLubyte *green,
  2171.                                              GLubyte *blue, GLubyte *alpha )
  2172. {
  2173.    GLint level;
  2174.    if (lambda<=0.5F) {
  2175.       level = 0;
  2176.    }
  2177.    else {
  2178.       GLint max = ctx->Texture.Current2D->Image[0]->MaxLog2;
  2179.       level = (GLint) (lambda + 0.499999F);
  2180.       if (level>max) {
  2181.          level = max;
  2182.       }
  2183.    }
  2184.    sample_2d_linear( ctx, ctx->Texture.Current2D->Image[level],
  2185.                      s, t, red, green, blue, alpha );
  2186. }
  2187.  
  2188.  
  2189.  
  2190. static void sample_2d_nearest_mipmap_linear( GLcontext *ctx,
  2191.                                              GLfloat lambda,
  2192.                                              GLfloat s, GLfloat t,
  2193.                                              GLubyte *red, GLubyte *green,
  2194.                                              GLubyte *blue, GLubyte *alpha )
  2195. {
  2196.    GLint max = ctx->Texture.Current2D->Image[0]->MaxLog2;
  2197.  
  2198.    if (lambda>=max) {
  2199.       sample_2d_nearest( ctx, ctx->Texture.Current2D->Image[max],
  2200.                          s, t, red, green, blue, alpha );
  2201.    }
  2202.    else {
  2203.       GLubyte red0, green0, blue0, alpha0;
  2204.       GLubyte red1, green1, blue1, alpha1;
  2205.       GLfloat f = frac(lambda);
  2206.       GLint level = (GLint) (lambda + 1.0F);
  2207.       level = CLAMP( level, 1, max );
  2208.       sample_2d_nearest( ctx, ctx->Texture.Current2D->Image[level-1], s, t,
  2209.                          &red0, &green0, &blue0, &alpha0 );
  2210.       sample_2d_nearest( ctx, ctx->Texture.Current2D->Image[level], s, t,
  2211.                          &red1, &green1, &blue1, &alpha1 );
  2212.       *red   = (1.0F-f)*red0   + f*red1;
  2213.       *green = (1.0F-f)*green0 + f*green1;
  2214.       *blue  = (1.0F-f)*blue0  + f*blue1;
  2215.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  2216.    }
  2217. }
  2218.  
  2219.  
  2220.  
  2221. static void sample_2d_linear_mipmap_linear( GLcontext *ctx,
  2222.                                             GLfloat lambda,
  2223.                                             GLfloat s, GLfloat t,
  2224.                                             GLubyte *red, GLubyte *green,
  2225.                                             GLubyte *blue, GLubyte *alpha )
  2226. {
  2227.    GLint max = ctx->Texture.Current2D->Image[0]->MaxLog2;
  2228.  
  2229.    if (lambda>=max) {
  2230.       sample_2d_linear( ctx, ctx->Texture.Current2D->Image[max],
  2231.                          s, t, red, green, blue, alpha );
  2232.    }
  2233.    else {
  2234.       GLubyte red0, green0, blue0, alpha0;
  2235.       GLubyte red1, green1, blue1, alpha1;
  2236.       GLfloat f = frac(lambda);
  2237.       GLint level = (GLint) (lambda + 1.0F);
  2238.       level = CLAMP( level, 1, max );
  2239.       sample_2d_linear( ctx, ctx->Texture.Current2D->Image[level-1], s, t,
  2240.                          &red0, &green0, &blue0, &alpha0 );
  2241.       sample_2d_linear( ctx, ctx->Texture.Current2D->Image[level], s, t,
  2242.                          &red1, &green1, &blue1, &alpha1 );
  2243.       *red   = (1.0F-f)*red0   + f*red1;
  2244.       *green = (1.0F-f)*green0 + f*green1;
  2245.       *blue  = (1.0F-f)*blue0  + f*blue1;
  2246.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  2247.    }
  2248. }
  2249.  
  2250.  
  2251.  
  2252.  
  2253. /*
  2254.  * Given an (s,t) texture coordinate and lambda (level of detail) value,
  2255.  * return a texture sample.
  2256.  */
  2257. static void sample_2d_texture( GLcontext *ctx,
  2258.                                GLfloat s, GLfloat t, GLfloat lambda,
  2259.                                GLubyte *red, GLubyte *green, GLubyte *blue,
  2260.                                GLubyte *alpha, GLfloat c )
  2261. {
  2262.    if (lambda>c) {
  2263.       /* minification */
  2264.       switch (ctx->Texture.Current2D->MinFilter) {
  2265.          case GL_NEAREST:
  2266.             sample_2d_nearest( ctx, ctx->Texture.Current2D->Image[0],
  2267.                                s, t, red, green, blue, alpha );
  2268.             break;
  2269.          case GL_LINEAR:
  2270.             sample_2d_linear( ctx, ctx->Texture.Current2D->Image[0],
  2271.                               s, t, red, green, blue, alpha );
  2272.             break;
  2273.          case GL_NEAREST_MIPMAP_NEAREST:
  2274.             sample_2d_nearest_mipmap_nearest( ctx, lambda, s, t,
  2275.                                               red, green, blue, alpha );
  2276.             break;
  2277.          case GL_LINEAR_MIPMAP_NEAREST:
  2278.             sample_2d_linear_mipmap_nearest( ctx, lambda, s, t,
  2279.                                              red, green, blue, alpha );
  2280.             break;
  2281.          case GL_NEAREST_MIPMAP_LINEAR:
  2282.             sample_2d_nearest_mipmap_linear( ctx, lambda, s, t,
  2283.                                              red, green, blue, alpha );
  2284.             break;
  2285.          case GL_LINEAR_MIPMAP_LINEAR:
  2286.             sample_2d_linear_mipmap_linear( ctx, lambda, s, t,
  2287.                                             red, green, blue, alpha );
  2288.             break;
  2289.          default:
  2290.             abort();
  2291.       }
  2292.    }
  2293.    else {
  2294.       /* magnification */
  2295.       switch (ctx->Texture.Current2D->MagFilter) {
  2296.          case GL_NEAREST:
  2297.             sample_2d_nearest( ctx, ctx->Texture.Current2D->Image[0],
  2298.                                s, t, red, green, blue, alpha );
  2299.             break;
  2300.          case GL_LINEAR:
  2301.             sample_2d_linear( ctx, ctx->Texture.Current2D->Image[0],
  2302.                               s, t, red, green, blue, alpha );
  2303.             break;
  2304.          default:
  2305.             abort();
  2306.       }
  2307.    }
  2308. }
  2309.  
  2310.  
  2311.  
  2312. /**********************************************************************/
  2313. /*                    3-D Texture Sampling Functions                  */
  2314. /**********************************************************************/
  2315.  
  2316. /*
  2317.  * Given a texture image and an (i,j,k) integer texel coordinate, return the
  2318.  * texel color.
  2319.  */
  2320. static void get_3d_texel( struct gl_texture_image *img,
  2321.                           GLint i, GLint j, GLint k,
  2322.                           GLubyte *red, GLubyte *green, GLubyte *blue,
  2323.                           GLubyte *alpha )
  2324. {
  2325.    GLint width = img->Width;    /* includes border */
  2326.    GLint height = img->Height;  /* includes border */
  2327.    GLint depth = img->Depth;    /* includes border */
  2328.    GLint rectarea;              /* = width * heigth */
  2329.    GLubyte *texel;
  2330.  
  2331.    rectarea = width*height;
  2332.  
  2333. #ifdef DEBUG
  2334.    if (i<0 || i>=width)  abort();
  2335.    if (j<0 || j>=height)  abort();
  2336.    if (k<0 || k>=depth)  abort();
  2337. #endif
  2338.  
  2339.    switch (img->Format) {
  2340.       case GL_ALPHA:
  2341.          *alpha = img->Data[ rectarea * k +  width * j + i ];
  2342.          return;
  2343.       case GL_LUMINANCE:
  2344.       case GL_INTENSITY:
  2345.          *red   = img->Data[ rectarea * k +  width * j + i ];
  2346.          return;
  2347.       case GL_LUMINANCE_ALPHA:
  2348.          texel = img->Data + ( rectarea * k + width * j + i) * 2;
  2349.          *red   = texel[0];
  2350.          *alpha = texel[1];
  2351.          return;
  2352.       case GL_RGB:
  2353.          texel = img->Data + (rectarea * k + width * j + i) * 3;
  2354.          *red   = texel[0];
  2355.          *green = texel[1];
  2356.          *blue  = texel[2];
  2357.          return;
  2358.       case GL_RGBA:
  2359.          texel = img->Data + (rectarea * k + width * j + i) * 4;
  2360.          *red   = texel[0];
  2361.          *green = texel[1];
  2362.          *blue  = texel[2];
  2363.          *alpha = texel[3];
  2364.          return;
  2365.       default:
  2366.          abort();
  2367.    }
  2368. }
  2369.  
  2370.  
  2371. /*
  2372.  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  2373.  */
  2374. static void sample_3d_nearest( GLcontext *ctx,
  2375.                                struct gl_texture_image *img,
  2376.                                GLfloat s, GLfloat t, GLfloat r,
  2377.                                GLubyte *red, GLubyte *green,
  2378.                                GLubyte *blue, GLubyte *alpha )
  2379. {
  2380.    GLint imgWidth = img->Width;   /* includes border, if any */
  2381.    GLint imgHeight = img->Height; /* includes border, if any */
  2382.    GLint width = img->Width2;     /* without border, power of two */
  2383.    GLint height = img->Height2;   /* without border, power of two */
  2384.    GLint depth = img->Depth2;     /* without border, power of two */
  2385.    GLint rectarea;                /* = width * height */
  2386.    GLint i, j, k;
  2387.    GLubyte *texel;
  2388.  
  2389.    rectarea = imgWidth * imgHeight;
  2390.  
  2391.    /* Clamp/Repeat S and convert to integer texel coordinate */
  2392.    if (ctx->Texture.Current3D->WrapS==GL_REPEAT) {
  2393.       /* s limited to [0,1) */
  2394.       /* i limited to [0,width-1] */
  2395.       i = (GLint) (s * width);
  2396.       i &= (width-1);
  2397.    }
  2398.    else {
  2399.       /* s limited to [0,1] */
  2400.       /* i limited to [0,width-1] */
  2401.       if (s<0.0F)       i = 0;
  2402.       else if (s>1.0F)  i = width-1;
  2403.       else              i = (GLint) (s * width);
  2404.    }
  2405.  
  2406.    /* Clamp/Repeat T and convert to integer texel coordinate */
  2407.    if (ctx->Texture.Current3D->WrapT==GL_REPEAT) {
  2408.       /* t limited to [0,1) */
  2409.       /* j limited to [0,height-1] */
  2410.       j = (GLint) (t * height);
  2411.       j &= (height-1);
  2412.    }
  2413.    else {
  2414.       /* t limited to [0,1] */
  2415.       /* j limited to [0,height-1] */
  2416.       if (t<0.0F)       j = 0;
  2417.       else if (t>1.0F)  j = height-1;
  2418.       else              j = (GLint) (t * height);
  2419.    }
  2420.  
  2421.    /* Clamp/Repeat R and convert to integer texel coordinate */
  2422.    if (ctx->Texture.Current3D->WrapR==GL_REPEAT) {
  2423.       /* r limited to [0,1) */
  2424.       /* k limited to [0,depth-1] */
  2425.       k = (GLint) (r * depth);
  2426.       k &= (depth-1);
  2427.    }
  2428.    else {
  2429.       /* r limited to [0,1] */
  2430.       /* k limited to [0,depth-1] */
  2431.       if (r<0.0F)       k = 0;
  2432.       else if (r>1.0F)  k = depth-1;
  2433.       else              k = (GLint) (r * depth);
  2434.    }
  2435.  
  2436.    switch (img->Format) {
  2437.       case GL_ALPHA:
  2438.          *alpha = img->Data[ rectarea * k + j * imgWidth + i ];
  2439.          return;
  2440.       case GL_LUMINANCE:
  2441.       case GL_INTENSITY:
  2442.          *red   = img->Data[ rectarea * k + j * imgWidth + i ];
  2443.          return;
  2444.       case GL_LUMINANCE_ALPHA:
  2445.          texel  = img->Data + ((rectarea * k + j * imgWidth + i) << 1);
  2446.          *red   = texel[0];
  2447.          *alpha = texel[1];
  2448.          return;
  2449.       case GL_RGB:
  2450.          texel = img->Data + ( rectarea * k + j * imgWidth + i) * 3;
  2451.          *red   = texel[0];
  2452.          *green = texel[1];
  2453.          *blue  = texel[2];
  2454.          return;
  2455.       case GL_RGBA:
  2456.          texel = img->Data + ((rectarea * k + j * imgWidth + i) << 2);
  2457.          *red   = texel[0];
  2458.          *green = texel[1];
  2459.          *blue  = texel[2];
  2460.          *alpha = texel[3];
  2461.          return;
  2462.       default:
  2463.          abort();
  2464.    }
  2465. }
  2466.  
  2467.  
  2468. /*
  2469.  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  2470.  */
  2471. static void sample_3d_linear( GLcontext *ctx,
  2472.                               struct gl_texture_image *img,
  2473.                               GLfloat s, GLfloat t, GLfloat r,
  2474.                               GLubyte *red, GLubyte *green,
  2475.                               GLubyte *blue, GLubyte *alpha )
  2476. {
  2477.    GLint width = img->Width2;
  2478.    GLint height = img->Height2;
  2479.    GLint depth = img->Depth2;
  2480.    GLint i0, j0, k0, i1, j1, k1;
  2481.    GLint i0border, j0border, k0border, i1border, j1border, k1border;
  2482.    GLfloat u, v, w;
  2483.  
  2484.    u = s * width;
  2485.    if (ctx->Texture.Current3D->WrapS==GL_REPEAT) {
  2486.       i0 = ((GLint) floor(u - 0.5F)) % width;
  2487.       i1 = (i0 + 1) & (width-1);
  2488.       i0border = i1border = 0;
  2489.    }
  2490.    else {
  2491.       i0 = (GLint) floor(u - 0.5F);
  2492.       i1 = i0 + 1;
  2493.       i0border = (i0<0) | (i0>=width);
  2494.       i1border = (i1<0) | (i1>=width);
  2495.    }
  2496.  
  2497.    v = t * height;
  2498.    if (ctx->Texture.Current3D->WrapT==GL_REPEAT) {
  2499.       j0 = ((GLint) floor(v - 0.5F)) % height;
  2500.       j1 = (j0 + 1) & (height-1);
  2501.       j0border = j1border = 0;
  2502.    }
  2503.    else {
  2504.       j0 = (GLint) floor(v - 0.5F);
  2505.       j1 = j0 + 1;
  2506.       j0border = (j0<0) | (j0>=height);
  2507.       j1border = (j1<0) | (j1>=height);
  2508.    }
  2509.  
  2510.    w = r * depth;
  2511.    if (ctx->Texture.Current3D->WrapR==GL_REPEAT) {
  2512.       k0 = ((GLint) floor(w - 0.5F)) % depth;
  2513.       k1 = (k0 + 1) & (depth-1);
  2514.       k0border = k1border = 0;
  2515.    }
  2516.    else {
  2517.       k0 = (GLint) floor(v - 0.5F);
  2518.       k1 = k0 + 1;
  2519.       k0border = (k0<0) | (k0>=depth);
  2520.       k1border = (k1<0) | (k1>=depth);
  2521.    }
  2522.  
  2523.    if (img->Border) {
  2524.       i0 += img->Border;
  2525.       i1 += img->Border;
  2526.       j0 += img->Border;
  2527.       j1 += img->Border;
  2528.       k0 += img->Border;
  2529.       k1 += img->Border;
  2530.       i0border = i1border = 0;
  2531.       j0border = j1border = 0;
  2532.       k0border = k1border = 0;
  2533.    }
  2534.    else {
  2535.       i0 &= (width-1);
  2536.       j0 &= (height-1);
  2537.       k0 &= (depth-1);
  2538.    }
  2539.  
  2540.    {
  2541.       GLfloat a = frac(u - 0.5F);
  2542.       GLfloat b = frac(v - 0.5F);
  2543.       GLfloat c = frac(w - 0.5F);
  2544.  
  2545.       GLint w000 = (GLint) ((1.0F-a)*(1.0F-b) * (1.0F-c) * 256.0F);
  2546.       GLint w010 = (GLint) (      a *(1.0F-b) * (1.0F-c) * 256.0F);
  2547.       GLint w001 = (GLint) ((1.0F-a)*      b  * (1.0F-c) * 256.0F);
  2548.       GLint w011 = (GLint) (      a *      b  * (1.0F-c) * 256.0F);
  2549.       GLint w100 = (GLint) ((1.0F-a)*(1.0F-b) * c * 256.0F);
  2550.       GLint w110 = (GLint) (      a *(1.0F-b) * c * 256.0F);
  2551.       GLint w101 = (GLint) ((1.0F-a)*      b  * c * 256.0F);
  2552.       GLint w111 = (GLint) (      a *      b  * c * 256.0F);
  2553.  
  2554.  
  2555.       GLubyte red000, green000, blue000, alpha000;
  2556.       GLubyte red010, green010, blue010, alpha010;
  2557.       GLubyte red001, green001, blue001, alpha001;
  2558.       GLubyte red011, green011, blue011, alpha011;
  2559.       GLubyte red100, green100, blue100, alpha100;
  2560.       GLubyte red110, green110, blue110, alpha110;
  2561.       GLubyte red101, green101, blue101, alpha101;
  2562.       GLubyte red111, green111, blue111, alpha111;
  2563.  
  2564.       if (k0border | i0border | j0border ) {
  2565.          red000   = ctx->Texture.Current3D->BorderColor[0];
  2566.          green000 = ctx->Texture.Current3D->BorderColor[1];
  2567.          blue000  = ctx->Texture.Current3D->BorderColor[2];
  2568.          alpha000 = ctx->Texture.Current3D->BorderColor[3];
  2569.       }
  2570.       else {
  2571.          get_3d_texel( img, i0, j0, k0, &red000, &green000, &blue000, &alpha000 );
  2572.       }
  2573.       if (k0border | i1border | j0border) {
  2574.          red010   = ctx->Texture.Current3D->BorderColor[0];
  2575.          green010 = ctx->Texture.Current3D->BorderColor[1];
  2576.          blue010  = ctx->Texture.Current3D->BorderColor[2];
  2577.          alpha010 = ctx->Texture.Current3D->BorderColor[3];
  2578.       }
  2579.       else {
  2580.          get_3d_texel( img, i1, j0, k0, &red010, &green010, &blue010, &alpha010 );
  2581.       }
  2582.       if (k0border | i0border | j1border) {
  2583.          red001   = ctx->Texture.Current3D->BorderColor[0];
  2584.          green001 = ctx->Texture.Current3D->BorderColor[1];
  2585.          blue001  = ctx->Texture.Current3D->BorderColor[2];
  2586.          alpha001 = ctx->Texture.Current3D->BorderColor[3];
  2587.       }
  2588.       else {
  2589.          get_3d_texel( img, i0, j1, k0, &red001, &green001, &blue001, &alpha001 );
  2590.       }
  2591.       if (k0border | i1border | j1border) {
  2592.          red011   = ctx->Texture.Current3D->BorderColor[0];
  2593.          green011 = ctx->Texture.Current3D->BorderColor[1];
  2594.          blue011  = ctx->Texture.Current3D->BorderColor[2];
  2595.          alpha011 = ctx->Texture.Current3D->BorderColor[3];
  2596.       }
  2597.       else {
  2598.          get_3d_texel( img, i1, j1, k0, &red011, &green011, &blue011, &alpha011 );
  2599.       }
  2600.  
  2601.       if (k1border | i0border | j0border ) {
  2602.          red100   = ctx->Texture.Current3D->BorderColor[0];
  2603.          green100 = ctx->Texture.Current3D->BorderColor[1];
  2604.          blue100  = ctx->Texture.Current3D->BorderColor[2];
  2605.          alpha100 = ctx->Texture.Current3D->BorderColor[3];
  2606.       }
  2607.       else {
  2608.          get_3d_texel( img, i0, j0, k1, &red100, &green100, &blue100, &alpha100 );
  2609.       }
  2610.       if (k1border | i1border | j0border) {
  2611.          red110   = ctx->Texture.Current3D->BorderColor[0];
  2612.          green110 = ctx->Texture.Current3D->BorderColor[1];
  2613.          blue110  = ctx->Texture.Current3D->BorderColor[2];
  2614.          alpha110 = ctx->Texture.Current3D->BorderColor[3];
  2615.       }
  2616.       else {
  2617.          get_3d_texel( img, i1, j0, k1, &red110, &green110, &blue110, &alpha110 );
  2618.       }
  2619.       if (k1border | i0border | j1border) {
  2620.          red101   = ctx->Texture.Current3D->BorderColor[0];
  2621.          green101 = ctx->Texture.Current3D->BorderColor[1];
  2622.          blue101  = ctx->Texture.Current3D->BorderColor[2];
  2623.          alpha101 = ctx->Texture.Current3D->BorderColor[3];
  2624.       }
  2625.       else {
  2626.          get_3d_texel( img, i0, j1, k1, &red101, &green101, &blue101, &alpha101 );
  2627.       }
  2628.       if (k1border | i1border | j1border) {
  2629.          red111   = ctx->Texture.Current3D->BorderColor[0];
  2630.          green111 = ctx->Texture.Current3D->BorderColor[1];
  2631.          blue111  = ctx->Texture.Current3D->BorderColor[2];
  2632.          alpha111 = ctx->Texture.Current3D->BorderColor[3];
  2633.       }
  2634.       else {
  2635.          get_3d_texel( img, i1, j1, k1, &red111, &green111, &blue111, &alpha111 );
  2636.       }
  2637.  
  2638.       *red   = (w000*red000   + w010*red010   + w001*red001   + w011*red011 +
  2639.                 w100*red100   + w110*red110   + w101*red101   + w111*red111  )
  2640.                 >> 8;
  2641.       *green = (w000*green000 + w010*green010 + w001*green001 + w011*green011 +
  2642.                 w100*green100 + w110*green110 + w101*green101 + w111*green111 )
  2643.                 >> 8;
  2644.       *blue  = (w000*blue000  + w010*blue010  + w001*blue001  + w011*blue011 +
  2645.                 w100*blue100  + w110*blue110  + w101*blue101  + w111*blue111 )
  2646.                 >> 8;
  2647.       *alpha = (w000*alpha000 + w010*alpha010 + w001*alpha001 + w011*alpha011 +
  2648.                 w100*alpha100 + w110*alpha110 + w101*alpha101 + w111*alpha111 )
  2649.                 >> 8;
  2650.    }
  2651. }
  2652.  
  2653.  
  2654. static void sample_3d_nearest_mipmap_nearest( GLcontext *ctx,
  2655.                                               GLfloat lambda,
  2656.                                               GLfloat s, GLfloat t, GLfloat r,
  2657.                                               GLubyte *red, GLubyte *green,
  2658.                                               GLubyte *blue, GLubyte *alpha )
  2659. {
  2660.    GLint level;
  2661.    if (lambda<=0.5F) {
  2662.       level = 0;
  2663.    }
  2664.    else {
  2665.       GLint widthlog2 = ctx->Texture.Current3D->Image[0]->WidthLog2;
  2666.       level = (GLint) (lambda + 0.499999F);
  2667.       if (level>widthlog2 ) {
  2668.          level = widthlog2;
  2669.       }
  2670.    }
  2671.    sample_3d_nearest( ctx, ctx->Texture.Current3D->Image[level],
  2672.                       s, t, r, red, green, blue, alpha );
  2673. }
  2674.  
  2675.  
  2676. static void sample_3d_linear_mipmap_nearest( GLcontext *ctx,
  2677.                                              GLfloat lambda,
  2678.                                              GLfloat s, GLfloat t, GLfloat r,
  2679.                                              GLubyte *red, GLubyte *green,
  2680.                                              GLubyte *blue, GLubyte *alpha )
  2681. {
  2682.    GLint level;
  2683.    if (lambda<=0.5F) {
  2684.       level = 0;
  2685.    }
  2686.    else {
  2687.       GLint widthlog2 = ctx->Texture.Current3D->Image[0]->WidthLog2;
  2688.       level = (GLint) (lambda + 0.499999F);
  2689.       if (level>widthlog2 ) {
  2690.          level = widthlog2;
  2691.       }
  2692.    }
  2693.    sample_3d_linear( ctx, ctx->Texture.Current3D->Image[level],
  2694.                      s, t, r, red, green, blue, alpha );
  2695. }
  2696.  
  2697.  
  2698. static void sample_3d_nearest_mipmap_linear( GLcontext *ctx,
  2699.                                              GLfloat lambda,
  2700.                                              GLfloat s, GLfloat t, GLfloat r,
  2701.                                              GLubyte *red, GLubyte *green,
  2702.                                              GLubyte *blue, GLubyte *alpha )
  2703. {
  2704.    GLint max = ctx->Texture.Current3D->Image[0]->MaxLog2;
  2705.  
  2706.    if (lambda>=max) {
  2707.       sample_3d_nearest( ctx, ctx->Texture.Current3D->Image[max],
  2708.                          s, t, r, red, green, blue, alpha );
  2709.    }
  2710.    else {
  2711.       GLubyte red0, green0, blue0, alpha0;
  2712.       GLubyte red1, green1, blue1, alpha1;
  2713.       GLfloat f = frac(lambda);
  2714.       GLint level = (GLint) (lambda + 1.0F);
  2715.       level = CLAMP( level, 1, max );
  2716.       sample_3d_nearest( ctx, ctx->Texture.Current3D->Image[level-1], s, t, r,
  2717.                          &red0, &green0, &blue0, &alpha0 );
  2718.       sample_3d_nearest( ctx, ctx->Texture.Current3D->Image[level], s, t, r,
  2719.                          &red1, &green1, &blue1, &alpha1 );
  2720.       *red   = (1.0F-f)*red1   + f*red0;
  2721.       *green = (1.0F-f)*green1 + f*green0;
  2722.       *blue  = (1.0F-f)*blue1  + f*blue0;
  2723.       *alpha = (1.0F-f)*alpha1 + f*alpha0;
  2724.    }
  2725. }
  2726.  
  2727.  
  2728. static void sample_3d_linear_mipmap_linear( GLcontext *ctx,
  2729.                                             GLfloat lambda,
  2730.                                             GLfloat s, GLfloat t, GLfloat r,
  2731.                                             GLubyte *red, GLubyte *green,
  2732.                                             GLubyte *blue, GLubyte *alpha )
  2733. {
  2734.    GLint max = ctx->Texture.Current3D->Image[0]->MaxLog2;
  2735.  
  2736.    if (lambda>=max) {
  2737.       sample_3d_linear( ctx, ctx->Texture.Current3D->Image[max],
  2738.                          s, t, r, red, green, blue, alpha );
  2739.    }
  2740.    else {
  2741.       GLubyte red0, green0, blue0, alpha0;
  2742.       GLubyte red1, green1, blue1, alpha1;
  2743.       GLfloat f = frac(lambda);
  2744.       GLint level = (GLint) (lambda + 1.0F);
  2745.       level = CLAMP( level, 1, max );
  2746.       sample_3d_linear( ctx, ctx->Texture.Current3D->Image[level-1], s, t, r,
  2747.                          &red0, &green0, &blue0, &alpha0 );
  2748.       sample_3d_linear( ctx, ctx->Texture.Current3D->Image[level], s, t, r,
  2749.                          &red1, &green1, &blue1, &alpha1 );
  2750.       *red   = (1.0F-f)*red1   + f*red0;
  2751.       *green = (1.0F-f)*green1 + f*green0;
  2752.       *blue  = (1.0F-f)*blue1  + f*blue0;
  2753.       *alpha = (1.0F-f)*alpha1 + f*alpha0;
  2754.    }
  2755. }
  2756.  
  2757.  
  2758. /*
  2759.  * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
  2760.  * return a texture sample.
  2761.  */
  2762. static void sample_3d_texture( GLcontext *ctx,
  2763.                                GLfloat s, GLfloat t, GLfloat r, GLfloat lambda,
  2764.                                GLubyte *red, GLubyte *green, GLubyte *blue,
  2765.                                GLubyte *alpha, GLfloat c )
  2766. {
  2767.    if (lambda>c) {
  2768.       /* minification */
  2769.       switch (ctx->Texture.Current3D->MinFilter) {
  2770.          case GL_NEAREST:
  2771.             sample_3d_nearest( ctx, ctx->Texture.Current3D->Image[0],
  2772.                                s, t, r, red, green, blue, alpha );
  2773.             break;
  2774.          case GL_LINEAR:
  2775.             sample_3d_linear( ctx, ctx->Texture.Current3D->Image[0],
  2776.                               s, t, r, red, green, blue, alpha );
  2777.             break;
  2778.          case GL_NEAREST_MIPMAP_NEAREST:
  2779.             sample_3d_nearest_mipmap_nearest( ctx, lambda, s, t, r,
  2780.                                               red, green, blue, alpha );
  2781.             break;
  2782.          case GL_LINEAR_MIPMAP_NEAREST:
  2783.             sample_3d_linear_mipmap_nearest( ctx, lambda, s, t, r,
  2784.                                              red, green, blue, alpha );
  2785.             break;
  2786.          case GL_NEAREST_MIPMAP_LINEAR:
  2787.             sample_3d_nearest_mipmap_linear( ctx, lambda, s, t, r,
  2788.                                              red, green, blue, alpha );
  2789.             break;
  2790.          case GL_LINEAR_MIPMAP_LINEAR:
  2791.             sample_3d_linear_mipmap_linear( ctx, lambda, s, t, r,
  2792.                                             red, green, blue, alpha );
  2793.             break;
  2794.          default:
  2795.             abort();
  2796.       }
  2797.    }
  2798.    else {
  2799.       /* magnification */
  2800.       switch (ctx->Texture.Current3D->MagFilter) {
  2801.          case GL_NEAREST:
  2802.             sample_3d_nearest( ctx, ctx->Texture.Current3D->Image[0],
  2803.                                s, t, r, red, green, blue, alpha );
  2804.             break;
  2805.          case GL_LINEAR:
  2806.             sample_3d_linear( ctx, ctx->Texture.Current3D->Image[0],
  2807.                               s, t, r, red, green, blue, alpha );
  2808.             break;
  2809.          default:
  2810.             abort();
  2811.       }
  2812.    }
  2813. }
  2814.  
  2815.  
  2816.  
  2817. /**********************************************************************/
  2818. /*                      Texture Application                           */
  2819. /**********************************************************************/
  2820.  
  2821.  
  2822.  
  2823. /*
  2824.  * Combine incoming fragment color with texel color to produce output color.
  2825.  * Input:  n - number of fragments
  2826.  *         format - base internal texture format
  2827.  *         env_mode - texture environment mode
  2828.  *         Rt, Gt, Bt, At - array of texel colors
  2829.  * InOut:  red, green, blue, alpha - incoming fragment colors modified
  2830.  *                                   by texel colors according to the
  2831.  *                                   texture environment mode.
  2832.  */
  2833. static void apply_texture( GLcontext *ctx,
  2834.          GLuint n, GLint format, GLenum env_mode,
  2835.      GLubyte red[], GLubyte green[], GLubyte blue[], GLubyte alpha[],
  2836.      GLubyte Rt[], GLubyte Gt[], GLubyte Bt[], GLubyte At[] )
  2837. {
  2838.    GLuint i;
  2839.    GLint Rc, Gc, Bc, Ac;
  2840.  
  2841.    if (!ctx->Visual->EightBitColor) {
  2842.       /* This is a hack!  Rescale input colors from [0,scale] to [0,255]. */
  2843.       GLfloat rscale = 255.0 * ctx->Visual->InvRedScale;
  2844.       GLfloat gscale = 255.0 * ctx->Visual->InvGreenScale;
  2845.       GLfloat bscale = 255.0 * ctx->Visual->InvBlueScale;
  2846.       GLfloat ascale = 255.0 * ctx->Visual->InvAlphaScale;
  2847.       for (i=0;i<n;i++) {
  2848.      red[i]   = (GLint) (red[i]   * rscale);
  2849.      green[i] = (GLint) (green[i] * gscale);
  2850.      blue[i]  = (GLint) (blue[i]  * bscale);
  2851.      alpha[i] = (GLint) (alpha[i] * ascale);
  2852.       }
  2853.    }
  2854.  
  2855. /*
  2856.  * Use (A*(B+1)) >> 8 as a fast approximation of (A*B)/255 for A
  2857.  * and B in [0,255]
  2858.  */
  2859. #define PROD(A,B)   (((GLint)(A) * (GLint)(B)+1) >> 8)
  2860.  
  2861.    switch (env_mode) {
  2862.       case GL_REPLACE:
  2863.      switch (format) {
  2864.         case GL_ALPHA:
  2865.            for (i=0;i<n;i++) {
  2866.           /* Cv = Cf */
  2867.                   /* Av = At */
  2868.                   alpha[i] = At[i];
  2869.            }
  2870.            break;
  2871.         case GL_LUMINANCE:
  2872.            for (i=0;i<n;i++) {
  2873.           /* Cv = Lt */
  2874.                   GLint Lt = Rt[i];
  2875.                   red[i] = green[i] = blue[i] = Lt;
  2876.                   /* Av = Af */
  2877.            }
  2878.            break;
  2879.         case GL_LUMINANCE_ALPHA:
  2880.            for (i=0;i<n;i++) {
  2881.                   GLint Lt = Rt[i];
  2882.           /* Cv = Lt */
  2883.           red[i] = green[i] = blue[i] = Lt;
  2884.           /* Av = At */
  2885.           alpha[i] = At[i];
  2886.            }
  2887.            break;
  2888.         case GL_INTENSITY:
  2889.            for (i=0;i<n;i++) {
  2890.           /* Cv = It */
  2891.                   GLint It = Rt[i];
  2892.                   red[i] = green[i] = blue[i] = It;
  2893.                   /* Av = It */
  2894.                   alpha[i] = It;
  2895.            }
  2896.            break;
  2897.         case GL_RGB:
  2898.            for (i=0;i<n;i++) {
  2899.           /* Cv = Ct */
  2900.           red[i]   = Rt[i];
  2901.           green[i] = Gt[i];
  2902.           blue[i]  = Bt[i];
  2903.           /* Av = Af */
  2904.            }
  2905.            break;
  2906.         case GL_RGBA:
  2907.            for (i=0;i<n;i++) {
  2908.           /* Cv = Ct */
  2909.           red[i]   = Rt[i];
  2910.           green[i] = Gt[i];
  2911.           blue[i]  = Bt[i];
  2912.           /* Av = At */
  2913.           alpha[i] = At[i];
  2914.            }
  2915.            break;
  2916.             default:
  2917.                abort();
  2918.      }
  2919.      break;
  2920.  
  2921.       case GL_MODULATE:
  2922.          switch (format) {
  2923.         case GL_ALPHA:
  2924.            for (i=0;i<n;i++) {
  2925.           /* Cv = Cf */
  2926.           /* Av = AfAt */
  2927.           alpha[i] = PROD( alpha[i], At[i] );
  2928.            }
  2929.            break;
  2930.         case GL_LUMINANCE:
  2931.            for (i=0;i<n;i++) {
  2932.           /* Cv = LtCf */
  2933.                   GLint Lt = Rt[i];
  2934.           red[i]   = PROD( red[i],   Lt );
  2935.           green[i] = PROD( green[i], Lt );
  2936.           blue[i]  = PROD( blue[i],  Lt );
  2937.           /* Av = Af */
  2938.            }
  2939.            break;
  2940.         case GL_LUMINANCE_ALPHA:
  2941.            for (i=0;i<n;i++) {
  2942.           /* Cv = CfLt */
  2943.                   GLint Lt = Rt[i];
  2944.           red[i]   = PROD( red[i],   Lt );
  2945.           green[i] = PROD( green[i], Lt );
  2946.           blue[i]  = PROD( blue[i],  Lt );
  2947.           /* Av = AfAt */
  2948.           alpha[i] = PROD( alpha[i], At[i] );
  2949.            }
  2950.            break;
  2951.         case GL_INTENSITY:
  2952.            for (i=0;i<n;i++) {
  2953.           /* Cv = CfIt */
  2954.                   GLint It = Rt[i];
  2955.           red[i]   = PROD( red[i],   It );
  2956.           green[i] = PROD( green[i], It );
  2957.           blue[i]  = PROD( blue[i],  It );
  2958.           /* Av = AfIt */
  2959.           alpha[i] = PROD( alpha[i], It );
  2960.            }
  2961.            break;
  2962.         case GL_RGB:
  2963.            for (i=0;i<n;i++) {
  2964.           /* Cv = CfCt */
  2965.           red[i]   = PROD( red[i],   Rt[i] );
  2966.           green[i] = PROD( green[i], Gt[i] );
  2967.           blue[i]  = PROD( blue[i],  Bt[i] );
  2968.           /* Av = Af */
  2969.            }
  2970.            break;
  2971.         case GL_RGBA:
  2972.            for (i=0;i<n;i++) {
  2973.           /* Cv = CfCt */
  2974.           red[i]   = PROD( red[i],   Rt[i] );
  2975.           green[i] = PROD( green[i], Gt[i] );
  2976.           blue[i]  = PROD( blue[i],  Bt[i] );
  2977.           /* Av = AfAt */
  2978.           alpha[i] = PROD( alpha[i], At[i] );
  2979.            }
  2980.            break;
  2981.             default:
  2982.                abort();
  2983.      }
  2984.      break;
  2985.  
  2986.       case GL_DECAL:
  2987.          switch (format) {
  2988.             case GL_ALPHA:
  2989.             case GL_LUMINANCE:
  2990.             case GL_LUMINANCE_ALPHA:
  2991.             case GL_INTENSITY:
  2992.                /* undefined */
  2993.                break;
  2994.         case GL_RGB:
  2995.            for (i=0;i<n;i++) {
  2996.           /* Cv = Ct */
  2997.           red[i]   = Rt[i];
  2998.           green[i] = Gt[i];
  2999.           blue[i]  = Bt[i];
  3000.           /* Av = Af */
  3001.            }
  3002.            break;
  3003.         case GL_RGBA:
  3004.            for (i=0;i<n;i++) {
  3005.           /* Cv = Cf(1-At) + CtAt */
  3006.           GLint t = At[i], s = 255 - t;
  3007.           red[i]   = PROD(red[i],  s) + PROD(Rt[i],t);
  3008.           green[i] = PROD(green[i],s) + PROD(Gt[i],t);
  3009.           blue[i]  = PROD(blue[i], s) + PROD(Bt[i],t);
  3010.           /* Av = Af */
  3011.            }
  3012.            break;
  3013.             default:
  3014.                abort();
  3015.      }
  3016.      break;
  3017.  
  3018.       case GL_BLEND:
  3019.          Rc = (GLint) (ctx->Texture.EnvColor[0] * 255.0F);
  3020.          Gc = (GLint) (ctx->Texture.EnvColor[1] * 255.0F);
  3021.          Bc = (GLint) (ctx->Texture.EnvColor[2] * 255.0F);
  3022.          Ac = (GLint) (ctx->Texture.EnvColor[2] * 255.0F);
  3023.      switch (format) {
  3024.         case GL_ALPHA:
  3025.            for (i=0;i<n;i++) {
  3026.           /* Cv = Cf */
  3027.           /* Av = AfAt */
  3028.                   alpha[i] = PROD(alpha[i], At[i]);
  3029.            }
  3030.            break;
  3031.             case GL_LUMINANCE:
  3032.            for (i=0;i<n;i++) {
  3033.           /* Cv = Cf(1-Lt) + CcLt */
  3034.           GLint Lt = Rt[i], s = 255 - Lt;
  3035.           red[i]   = PROD(red[i],  s) + PROD(Rc,  Lt);
  3036.           green[i] = PROD(green[i],s) + PROD(Gc,Lt);
  3037.           blue[i]  = PROD(blue[i], s) + PROD(Bc, Lt);
  3038.           /* Av = Af */
  3039.            }
  3040.            break;
  3041.         case GL_LUMINANCE_ALPHA:
  3042.            for (i=0;i<n;i++) {
  3043.           /* Cv = Cf(1-Lt) + CcLt */
  3044.           GLint Lt = Rt[i], s = 255 - Lt;
  3045.           red[i]   = PROD(red[i],  s) + PROD(Rc,  Lt);
  3046.           green[i] = PROD(green[i],s) + PROD(Gc,Lt);
  3047.           blue[i]  = PROD(blue[i], s) + PROD(Bc, Lt);
  3048.           /* Av = AfAt */
  3049.           alpha[i] = PROD(alpha[i],At[i]);
  3050.            }
  3051.            break;
  3052.             case GL_INTENSITY:
  3053.            for (i=0;i<n;i++) {
  3054.           /* Cv = Cf(1-It) + CcLt */
  3055.           GLint It = Rt[i], s = 255 - It;
  3056.           red[i]   = PROD(red[i],  s) + PROD(Rc,It);
  3057.           green[i] = PROD(green[i],s) + PROD(Gc,It);
  3058.           blue[i]  = PROD(blue[i], s) + PROD(Bc,It);
  3059.                   /* Av = Af(1-It) + Ac*It */
  3060.                   alpha[i] = PROD(alpha[i],s) + PROD(Ac,It);
  3061.                }
  3062.                break;
  3063.         case GL_RGB:
  3064.            for (i=0;i<n;i++) {
  3065.           /* Cv = Cf(1-Ct) + CcCt */
  3066.           red[i]   = PROD(red[i],  (255-Rt[i])) + PROD(Rc,Rt[i]);
  3067.           green[i] = PROD(green[i],(255-Gt[i])) + PROD(Gc,Gt[i]);
  3068.           blue[i]  = PROD(blue[i], (255-Bt[i])) + PROD(Bc,Bt[i]);
  3069.           /* Av = Af */
  3070.            }
  3071.            break;
  3072.         case GL_RGBA:
  3073.            for (i=0;i<n;i++) {
  3074.           /* Cv = Cf(1-Ct) + CcCt */
  3075.           red[i]   = PROD(red[i],  (255-Rt[i])) + PROD(Rc,Rt[i]);
  3076.           green[i] = PROD(green[i],(255-Gt[i])) + PROD(Gc,Gt[i]);
  3077.           blue[i]  = PROD(blue[i], (255-Bt[i])) + PROD(Bc,Bt[i]);
  3078.           /* Av = AfAt */
  3079.           alpha[i] = PROD(alpha[i],At[i]);
  3080.            }
  3081.            break;
  3082.      }
  3083.      break;
  3084.  
  3085.       default:
  3086.          abort();
  3087.    }
  3088. #undef PROD
  3089.  
  3090.    if (!ctx->Visual->EightBitColor) {
  3091.       /* This is a hack!  Rescale input colors from [0,255] to [0,scale]. */
  3092.       GLfloat rscale = ctx->Visual->RedScale   * (1.0F/ 255.0F);
  3093.       GLfloat gscale = ctx->Visual->GreenScale * (1.0F/ 255.0F);
  3094.       GLfloat bscale = ctx->Visual->BlueScale  * (1.0F/ 255.0F);
  3095.       GLfloat ascale = ctx->Visual->AlphaScale * (1.0F/ 255.0F);
  3096.       for (i=0;i<n;i++) {
  3097.      red[i]   = (GLint) (red[i]   * rscale);
  3098.      green[i] = (GLint) (green[i] * gscale);
  3099.      blue[i]  = (GLint) (blue[i]  * bscale);
  3100.      alpha[i] = (GLint) (alpha[i] * ascale);
  3101.       }
  3102.    }
  3103. }
  3104.  
  3105.  
  3106.  
  3107. /*
  3108.  * Given an array of fragment colors and texture coordinates, apply
  3109.  * 1-D texturing to the fragments.
  3110.  * Input:  n - number of fragments
  3111.  *         s - array of texture coordinate s values
  3112.  *         lambda - array of lambda values
  3113.  * InOut:  red, green, blue, alpha - incoming and modifed fragment colors
  3114.  */
  3115. void gl_texture_pixels_1d( GLcontext *ctx,
  3116.                            GLuint n, GLfloat s[], GLfloat lambda[],
  3117.                GLubyte red[], GLubyte green[],
  3118.                GLubyte blue[], GLubyte alpha[] )
  3119. {
  3120.    GLubyte tred[PB_SIZE];
  3121.    GLubyte tgreen[PB_SIZE];
  3122.    GLubyte tblue[PB_SIZE];
  3123.    GLubyte talpha[PB_SIZE];
  3124.    GLuint  i;
  3125.    GLfloat c;
  3126.  
  3127.    if (!ctx->Texture.Current1D->Complete) {
  3128.       return;
  3129.    }
  3130.  
  3131.    /* Compute c, the min/mag filter threshold. */
  3132.    if (ctx->Texture.Current1D->MagFilter==GL_LINEAR
  3133.        && (ctx->Texture.Current1D->MinFilter==GL_NEAREST_MIPMAP_NEAREST ||
  3134.            ctx->Texture.Current1D->MinFilter==GL_LINEAR_MIPMAP_NEAREST)) {
  3135.       c = 0.5F;
  3136.    }
  3137.    else {
  3138.       c = 0.0F;
  3139.    }
  3140.  
  3141.    /* Sample the texture. */
  3142.    if (lambda) {
  3143.       /* minfilter!=magfilter or using mipmaps */
  3144.       for (i=0;i<n;i++)
  3145.      sample_1d_texture( ctx, s[i],lambda[i],
  3146.                             &tred[i],&tgreen[i],&tblue[i],&talpha[i],c);
  3147.    } 
  3148.    else {
  3149.       /* use same filter for minification and magnification */
  3150.       if (ctx->Texture.Current1D->MagFilter==GL_NEAREST) {
  3151.          struct gl_texture_image *img = ctx->Texture.Current1D->Image[0];
  3152.          for (i=0;i<n;i++) {
  3153.             sample_1d_nearest( ctx, img, s[i],
  3154.                                &tred[i], &tgreen[i], &tblue[i], &talpha[i] );
  3155.          }
  3156.       }
  3157.       else {
  3158.          /* mag filter must be GL_LINEAR */
  3159.          struct gl_texture_image *img = ctx->Texture.Current1D->Image[0];
  3160.          for (i=0;i<n;i++) {
  3161.             sample_1d_linear( ctx, img, s[i],
  3162.                               &tred[i], &tgreen[i], &tblue[i], &talpha[i] );
  3163.          }
  3164.       }
  3165.    }
  3166.  
  3167.    /* Modify incoming fragment colors according to sampled texels */
  3168.    apply_texture( ctx, n,
  3169.                   ctx->Texture.Current1D->Image[0]->Format,
  3170.                   ctx->Texture.EnvMode,
  3171.           red, green, blue, alpha,
  3172.                   tred, tgreen, tblue, talpha );
  3173. }
  3174.  
  3175.  
  3176.  
  3177. /*
  3178.  * Given an array of fragment colors and texture coordinates, apply
  3179.  * 2-D texturing to the fragments.
  3180.  * Input:  n - number of fragments
  3181.  *         s,s - array of texture coordinate (s,t) values
  3182.  *         lambda - array of lambda values
  3183.  * InOut:  red, green, blue, alpha - incoming and modifed fragment colors
  3184.  */
  3185. void gl_texture_pixels_2d( GLcontext *ctx,
  3186.                            GLuint n,
  3187.                GLfloat s[], GLfloat t[], GLfloat lambda[],
  3188.                GLubyte red[], GLubyte green[],
  3189.                GLubyte blue[], GLubyte alpha[] )
  3190. {
  3191.    GLubyte tred[PB_SIZE];
  3192.    GLubyte tgreen[PB_SIZE];
  3193.    GLubyte tblue[PB_SIZE];
  3194.    GLubyte talpha[PB_SIZE];
  3195.    GLuint i;
  3196.    GLfloat c;
  3197.  
  3198.    if (!ctx->Texture.Current2D->Complete) {
  3199.       return;
  3200.    }
  3201.  
  3202.    /* Compute c, the min/mag filter threshold. */
  3203.    if (ctx->Texture.Current2D->MagFilter==GL_LINEAR
  3204.        && (ctx->Texture.Current2D->MinFilter==GL_NEAREST_MIPMAP_NEAREST ||
  3205.            ctx->Texture.Current2D->MinFilter==GL_LINEAR_MIPMAP_NEAREST)) {
  3206.       c = 0.5F;
  3207.    }
  3208.    else {
  3209.       c = 0.0F;
  3210.    }
  3211.  
  3212.    /* Sample the texture. */
  3213.    if (lambda) {
  3214.       /* minfilter!=magfilter or using mipmaps */
  3215.       for (i=0;i<n;i++) {
  3216.      sample_2d_texture( ctx, s[i], t[i], lambda[i],
  3217.                 &tred[i], &tgreen[i], &tblue[i], &talpha[i], c);
  3218.       }
  3219.    }
  3220.    else {
  3221.       /* use same filter for minification and magnification */
  3222.       if (ctx->Texture.Current2D->MagFilter==GL_NEAREST) {
  3223.          struct gl_texture_image *img = ctx->Texture.Current2D->Image[0];
  3224.          for (i=0;i<n;i++) {
  3225.             sample_2d_nearest( ctx, img, s[i], t[i],
  3226.                                &tred[i], &tgreen[i], &tblue[i], &talpha[i] );
  3227.          }
  3228.       }
  3229.       else {
  3230.          /* mag filter must be GL_LINEAR */
  3231.          struct gl_texture_image *img = ctx->Texture.Current2D->Image[0];
  3232.          for (i=0;i<n;i++) {
  3233.             sample_2d_linear( ctx, img, s[i], t[i],
  3234.                               &tred[i], &tgreen[i], &tblue[i], &talpha[i] );
  3235.          }
  3236.       }
  3237.    }
  3238.  
  3239.    apply_texture( ctx, n,
  3240.                   ctx->Texture.Current2D->Image[0]->Format,
  3241.                   ctx->Texture.EnvMode,
  3242.           red, green, blue, alpha,
  3243.                   tred, tgreen, tblue, talpha );
  3244. }
  3245.  
  3246.  
  3247.  
  3248. /*
  3249.  * Given an array of fragment colors and texture coordinates, apply
  3250.  * 3-D texturing to the fragments.
  3251.  * Input:  n - number of fragments
  3252.  *         s,t,r - array of texture coordinate (s,t,r) values
  3253.  *         lambda - array of lambda values
  3254.  * InOut:  red, green, blue, alpha - incoming and modifed fragment colors
  3255.  */
  3256. void gl_texture_pixels_3d( GLcontext *ctx,
  3257.                            GLuint n,
  3258.                            GLfloat s[], GLfloat t[], GLfloat r[],
  3259.                            GLfloat lambda[],
  3260.                            GLubyte red[], GLubyte green[],
  3261.                            GLubyte blue[], GLubyte alpha[] )
  3262. {
  3263.    GLubyte tred[PB_SIZE];
  3264.    GLubyte tgreen[PB_SIZE];
  3265.    GLubyte tblue[PB_SIZE];
  3266.    GLubyte talpha[PB_SIZE];
  3267.    GLuint i;
  3268.    GLfloat c;
  3269.  
  3270.    if (!ctx->Texture.Current3D->Complete) {
  3271.       return;
  3272.    }
  3273.  
  3274.    /* Compute c, the min/mag filter threshold. */
  3275.    if (ctx->Texture.Current3D->MagFilter==GL_LINEAR
  3276.        && (ctx->Texture.Current3D->MinFilter==GL_NEAREST_MIPMAP_NEAREST ||
  3277.            ctx->Texture.Current3D->MinFilter==GL_LINEAR_MIPMAP_NEAREST)) {
  3278.       c = 0.5F;
  3279.    }
  3280.    else {
  3281.       c = 0.0F;
  3282.    }
  3283.  
  3284.    /* Sample the texture. */
  3285.    if (lambda) {
  3286.       /* minfilter!=magfilter or using mipmaps */
  3287.       for (i=0;i<n;i++) {
  3288.          sample_3d_texture( ctx, s[i], t[i], r[i], lambda[i],
  3289.                             &tred[i], &tgreen[i], &tblue[i], &talpha[i], c);
  3290.       }
  3291.    }
  3292.    else {
  3293.       /* use same filter for minification and magnification */
  3294.       if (ctx->Texture.Current3D->MagFilter==GL_NEAREST) {
  3295.          struct gl_texture_image *img = ctx->Texture.Current3D->Image[0];
  3296.          for (i=0;i<n;i++) {
  3297.             sample_3d_nearest( ctx, img, s[i], t[i], r[i],
  3298.                                &tred[i], &tgreen[i], &tblue[i], &talpha[i] );
  3299.          }
  3300.       }
  3301.       else {
  3302.          /* mag filter must be GL_LINEAR */
  3303.          struct gl_texture_image *img = ctx->Texture.Current3D->Image[0];
  3304.          for (i=0;i<n;i++) {
  3305.             sample_3d_linear( ctx, img, s[i], t[i], r[i],
  3306.                               &tred[i], &tgreen[i], &tblue[i], &talpha[i] );
  3307.          }
  3308.       }
  3309.    }
  3310.  
  3311.    apply_texture( ctx, n,
  3312.                   ctx->Texture.Current3D->Image[0]->Format,
  3313.                   ctx->Texture.EnvMode,
  3314.                   red, green, blue, alpha,
  3315.                   tred, tgreen, tblue, talpha );
  3316. }
  3317.  
  3318.  
  3319.  
  3320. /*
  3321.  * This is called by gl_update_state() if the NEW_TEXTURING bit in
  3322.  * ctx->NewState is set.  Basically, we check if we have a complete set
  3323.  * of mipmaps when mipmapping is enabled.
  3324.  */
  3325. void gl_update_texture_state( GLcontext *ctx )
  3326. {
  3327.    GLint i;
  3328.    struct gl_texture_object *t;
  3329.  
  3330.    for (t = ctx->Shared->TexObjectList; t; t = t->Next) {
  3331.  
  3332.       /*
  3333.        * Determine if we have a complete set of mipmaps
  3334.        */
  3335.       t->Complete = GL_TRUE;  /* be optimistic */
  3336.       if (   t->MinFilter==GL_NEAREST_MIPMAP_NEAREST
  3337.           || t->MinFilter==GL_LINEAR_MIPMAP_NEAREST
  3338.           || t->MinFilter==GL_NEAREST_MIPMAP_LINEAR
  3339.           || t->MinFilter==GL_LINEAR_MIPMAP_LINEAR) {
  3340.  
  3341.          /* Test dimension-independent attributes */
  3342.          for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  3343.             if (t->Image[i]) {
  3344.                if (!t->Image[i]->Data) {
  3345.                   t->Complete = GL_FALSE;
  3346.                   break;
  3347.                }
  3348.                if (t->Image[i]->Format != t->Image[0]->Format) {
  3349.                   t->Complete = GL_FALSE;
  3350.                   break;
  3351.                }
  3352.                if (t->Image[i]->Border != t->Image[0]->Border) {
  3353.                   t->Complete = GL_FALSE;
  3354.                   break;
  3355.                }
  3356.             }
  3357.          }
  3358.  
  3359.          if (t->Dimensions==1) {
  3360.             if (t->Image[0]) {
  3361.                /* Test 1-D mipmaps */
  3362.                GLuint width = t->Image[0]->Width2;
  3363.                for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  3364.                   if (width>1) {
  3365.                      width /= 2;
  3366.                   }
  3367.                   if (!t->Image[i]) {
  3368.                      t->Complete = GL_FALSE;
  3369.                      break;
  3370.                   }
  3371.                   if (!t->Image[i]->Data) {
  3372.                      t->Complete = GL_FALSE;
  3373.                      break;
  3374.                   }
  3375.                   if (t->Image[i]->Format != t->Image[0]->Format) {
  3376.                      t->Complete = GL_FALSE;
  3377.                      break;
  3378.                   }
  3379.                   if (t->Image[i]->Border != t->Image[0]->Border) {
  3380.                      t->Complete = GL_FALSE;
  3381.                      break;
  3382.                   }
  3383.                   if (t->Image[i]->Width2 != width ) {
  3384.                      t->Complete = GL_FALSE;
  3385.                      break;
  3386.                   }
  3387.                   if (width==1) {
  3388.                      break;
  3389.                   }
  3390.                }
  3391.             }
  3392.             else {
  3393.                /* Image[0] missing, this is bad */
  3394.                t->Complete = GL_FALSE;
  3395.             }
  3396.          }
  3397.          else if (t->Dimensions==2) {
  3398.             if (t->Image[0]) {
  3399.                /* Test 2-D mipmaps */
  3400.                GLuint width = t->Image[0]->Width2;
  3401.                GLuint height = t->Image[0]->Height2;
  3402.                for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  3403.                   if (width>1) {
  3404.                      width /= 2;
  3405.                   }
  3406.                   if (height>1) {
  3407.                      height /= 2;
  3408.                   }
  3409.                   if (!t->Image[i]) {
  3410.                      t->Complete = GL_FALSE;
  3411.                      break;
  3412.                   }
  3413.                   if (t->Image[i]->Width2 != width) {
  3414.                      t->Complete = GL_FALSE;
  3415.                      break;
  3416.                   }
  3417.                   if (t->Image[i]->Height2 != height) {
  3418.                      t->Complete = GL_FALSE;
  3419.                      break;
  3420.                   }
  3421.                   if (width==1 && height==1) {
  3422.                      break;
  3423.                   }
  3424.                }
  3425.             }
  3426.             else {
  3427.                /* Image[0] is missing, this is bad */
  3428.                t->Complete = GL_FALSE;
  3429.             }
  3430.          }
  3431.          else if (t->Dimensions==3) {
  3432.             if (t->Image[0]) {
  3433.                /* Test 3-D mipmaps */
  3434.                GLuint width = t->Image[0]->Width2;
  3435.                GLuint height = t->Image[0]->Height2;
  3436.                GLuint depth = t->Image[0]->Depth2;
  3437.                for (i=1; i<MAX_TEXTURE_LEVELS; i++) {
  3438.                   if (width>1) {
  3439.                      width /= 2;
  3440.                   }
  3441.                   if (height>1) {
  3442.                      height /= 2;
  3443.                   }
  3444.                   if (depth>1) {
  3445.                      depth /= 2;
  3446.                   }
  3447.                   if (!t->Image[i]) {
  3448.                      t->Complete = GL_FALSE;
  3449.                      break;
  3450.                   }
  3451.                   if (t->Image[i]->Width2 != width) {
  3452.                      t->Complete = GL_FALSE;
  3453.                      break;
  3454.                   }
  3455.                   if (t->Image[i]->Height2 != height) {
  3456.                      t->Complete = GL_FALSE;
  3457.                      break;
  3458.                   }
  3459.                   if (t->Image[i]->Depth2 != depth) {
  3460.                      t->Complete = GL_FALSE;
  3461.                      break;
  3462.                   }
  3463.                   if (width==1 && height==1 && depth==1) {
  3464.                      break;
  3465.                   }
  3466.                }
  3467.             }
  3468.             else {
  3469.                /* Image[0] is missing, this is bad */
  3470.                t->Complete = GL_FALSE;
  3471.             }
  3472.          }
  3473.          else {
  3474.             /* Dimensions = ??? */
  3475.             gl_problem(ctx, "Bug in gl_update_texture_state\n");
  3476.          }
  3477.       }
  3478.       else {
  3479.          /* not mipmapping, only need the level 0 texture image */
  3480.          if (!t->Image[0] || !t->Image[0]->Data) {
  3481.             t->Complete = GL_FALSE;
  3482.          }
  3483.       }
  3484.    }
  3485. }
  3486.  
  3487.  
  3488.  
  3489. /*
  3490.  * Check if texturing is enabled.  Remember, if any texture images
  3491.  * (mipmap levels) are missing, it's as if texturing is disabled.
  3492.  * Return:  GL_TRUE if texturing is enabled and all is well, else GL_FALSE
  3493.  */
  3494. GLboolean gl_texturing_enabled( GLcontext *ctx )
  3495. {
  3496.    if ((ctx->Texture.Enabled & TEXTURE_3D) && ctx->Texture.Current3D->Complete)
  3497.       return GL_TRUE;
  3498.    else if ((ctx->Texture.Enabled & TEXTURE_2D) && ctx->Texture.Current2D->Complete)
  3499.       return GL_TRUE;
  3500.    else if ((ctx->Texture.Enabled & TEXTURE_1D) && ctx->Texture.Current1D->Complete)
  3501.       return GL_TRUE;
  3502.    else
  3503.       return GL_FALSE;
  3504. }
  3505.